update fields

This commit is contained in:
Denis Angell
2024-05-28 13:49:40 +02:00
parent ba2422929a
commit c77d53b810
9 changed files with 114 additions and 62 deletions

View File

@@ -110,8 +110,8 @@ XRPNotCreated::visitEntry(
drops_ -= (*before)[sfAmount].xrp().drops();
break;
case ltOPTION_OFFER:
if (isXRP((*before)[sfAmount]))
drops_ -= (*before)[sfAmount].xrp().drops();
if (isXRP((*before)[sfLockedBalance]))
drops_ -= (*before)[sfLockedBalance].xrp().drops();
break;
default:
break;
@@ -136,8 +136,8 @@ XRPNotCreated::visitEntry(
drops_ += (*after)[sfAmount].xrp().drops();
break;
case ltOPTION_OFFER:
if (!isDelete && isXRP((*after)[sfAmount]))
drops_ += (*after)[sfAmount].xrp().drops();
if (!isDelete && isXRP((*after)[sfLockedBalance]))
drops_ += (*after)[sfLockedBalance].xrp().drops();
break;
default:
break;

View File

@@ -49,8 +49,8 @@ OptionCreate::preflight(PreflightContext const& ctx)
}
auto const flags = ctx.tx.getFlags();
std::optional<uint256> const swapID = ctx.tx[~sfInvoiceID];
std::uint32_t const quantity = ctx.tx.getFieldU32(sfQualityIn);
std::optional<uint256> const swapID = ctx.tx[~sfSwapID];
std::uint32_t const quantity = ctx.tx.getFieldU32(sfQuantity);
bool const isClose = (flags & tfPosition) != 0;
@@ -124,7 +124,7 @@ sealOption(
bool const _isSell = (flags & tfAction) != 0;
// Skip Sealed Options
if (sleItem->getFieldU32(sfQualityOut) == 0)
if (sleItem->getFieldU32(sfToSeal) == 0)
{
continue;
}
@@ -132,7 +132,7 @@ sealOption(
// looking for oposite option position.
if (_isPut == isPut && _isSell != isSell)
{
uint256 const sealID = sleItem->getFieldH256(sfInvoiceID);
uint256 const sealID = sleItem->getFieldH256(sfSwapID);
if (sealID.isNonZero())
{
continue;
@@ -159,11 +159,11 @@ OptionCreate::doApply()
beast::Journal const& j = ctx_.journal;
AccountID const srcAccID = ctx_.tx.getAccountID(sfAccount);
uint256 const optionID = ctx_.tx.getFieldH256(sfOfferID);
uint256 const optionID = ctx_.tx.getFieldH256(sfOptionID);
auto const flags = ctx_.tx.getFlags();
STAmount const premium = ctx_.tx.getFieldAmount(sfAmount);
std::uint32_t const quantity = ctx_.tx.getFieldU32(sfQualityIn);
std::optional<uint256> const swapID = ctx_.tx[~sfInvoiceID];
std::uint32_t const quantity = ctx_.tx.getFieldU32(sfQuantity);
std::optional<uint256> const swapID = ctx_.tx[~sfSwapID];
STAmount const totalPremium =
STAmount(premium.issue(), (premium.mantissa() * quantity));
@@ -176,7 +176,7 @@ OptionCreate::doApply()
if (!sleOptionAcc)
return tecINTERNAL;
STAmount const strikePrice = sleOptionAcc->getFieldAmount(sfAmount);
STAmount const strikePrice = sleOptionAcc->getFieldAmount(sfStrikePrice);
std::uint32_t const expiration = sleOptionAcc->getFieldU32(sfExpiration);
STAmount const quantityShares = STAmount(strikePrice.issue(), isXRP(premium) ? quantity * 1000000 : quantity);
@@ -184,6 +184,11 @@ OptionCreate::doApply()
bool const isSell = (flags & tfAction) != 0;
bool const isClose = (flags & tfPosition) != 0;
// std::cout << "OptionCreate.getIssuer(): " << strikePrice.getIssuer() << "\n";
// std::cout << "OptionCreate.getCurrency(): " << strikePrice.getCurrency() << "\n";
// std::cout << "OptionCreate.mantissa(): " << strikePrice.mantissa() << "\n";
// std::cout << "OptionCreate.expiration: " << expiration << "\n";
auto optionBookDirKeylet = keylet::optionBook(
strikePrice.getIssuer(),
strikePrice.getCurrency(),
@@ -202,9 +207,9 @@ OptionCreate::doApply()
JLOG(j.warn()) << "Updating Sealed Offer: sealID";
auto sealedKeylet = ripple::keylet::unchecked(*sealID);
auto sealedOption = sb.peek(sealedKeylet);
sealedOption->setFieldH256(sfInvoiceID, optionOfferKeylet.key);
uint32_t currSealed = sealedOption->getFieldU32(sfQualityOut);
sealedOption->setFieldU32(sfQualityOut, currSealed - quantity);
sealedOption->setFieldH256(sfSwapID, optionOfferKeylet.key);
uint32_t currSealed = sealedOption->getFieldU32(sfToSeal);
sealedOption->setFieldU32(sfToSeal, currSealed - quantity);
oppAccID = sealedOption->getAccountID(sfOwner);
sb.update(sealedOption);
}
@@ -248,23 +253,22 @@ OptionCreate::doApply()
optionOffer->setFlag(flags);
optionOffer->setAccountID(sfOwner, srcAccID);
optionOffer->setFieldU64(sfOwnerNode, *page);
optionOffer->setFieldH256(sfOfferID, optionID);
optionOffer->setFieldU32(sfQualityIn, quantity);
optionOffer->setFieldU32(sfQualityOut, quantity);
optionOffer->setFieldAmount(sfTakerPays, STAmount(0)); // Premium
optionOffer->setFieldAmount(sfAmount, STAmount(0)); // Locked
optionOffer->setFieldH256(sfOptionID, optionID);
optionOffer->setFieldU32(sfQuantity, quantity);
optionOffer->setFieldU32(sfToSeal, quantity);
optionOffer->setFieldAmount(sfAmount, premium); // Premium
optionOffer->setFieldAmount(sfLockedBalance, STAmount(0)); // Locked
if (sealID)
{
JLOG(j.warn()) << "Updating Option Offer: sealID";
optionOffer->setFieldH256(sfInvoiceID, *sealID);
optionOffer->setFieldU32(sfQualityOut, 0);
optionOffer->setFieldH256(sfSwapID, *sealID);
optionOffer->setFieldU32(sfToSeal, 0);
}
if (isSell)
{
JLOG(j.warn()) << "Updating Option Offer: isSell";
// Update the locked balance and premium
optionOffer->setFieldAmount(sfTakerPays, premium); // Premium
optionOffer->setFieldAmount(sfAmount, quantityShares); // Locked
// Update the locked balance
optionOffer->setFieldAmount(sfLockedBalance, quantityShares); // Locked
}
Option const option{
@@ -305,7 +309,7 @@ OptionCreate::doApply()
{
JLOG(j.warn()) << "Updating Option Offer: isClose";
auto optionOffer = sb.peek(optionOfferKeylet);
uint256 const sealID = optionOffer->getFieldH256(sfInvoiceID);
uint256 const sealID = optionOffer->getFieldH256(sfSwapID);
if (!sealID)
{
JLOG(j.warn())
@@ -321,15 +325,15 @@ OptionCreate::doApply()
JLOG(j.warn()) << "OptionCreate: Swap Option does not exist.";
return tecINTERNAL;
}
swapOption->setFieldH256(sfInvoiceID, optionOfferKeylet.key);
swapOption->setFieldH256(sfSwapID, optionOfferKeylet.key);
sb.update(swapOption);
// Update New Option
optionOffer->setFieldH256(sfInvoiceID, *swapID);
optionOffer->setFieldH256(sfSwapID, *swapID);
sb.update(optionOffer);
// Erase Swap Sealed Option
uint256 const swapSealedID = swapOption->getFieldH256(sfInvoiceID);
uint256 const swapSealedID = swapOption->getFieldH256(sfSwapID);
if (!swapSealedID)
{
JLOG(j.warn()) << "OptionCreate: Swap Option is not sealed.";

View File

@@ -60,8 +60,8 @@ OptionExecute::doApply()
beast::Journal const& j = ctx_.journal;
AccountID const srcAccID = ctx_.tx.getAccountID(sfAccount);
uint256 const optionID = ctx_.tx.getFieldH256(sfOfferID);
uint256 const offerID = ctx_.tx.getFieldH256(sfInvoiceID);
uint256 const optionID = ctx_.tx.getFieldH256(sfOptionID);
uint256 const offerID = ctx_.tx.getFieldH256(sfSwapID);
auto const flags = ctx_.tx.getFlags();
auto sleSrcAcc = sb.peek(keylet::account(srcAccID));
@@ -74,7 +74,7 @@ OptionExecute::doApply()
return tecNO_TARGET;
AccountID const ownrAccID = sleOptionOffer->getAccountID(sfOwner);
auto const sealedID = sleOptionOffer->getFieldH256(sfInvoiceID);
auto const sealedID = sleOptionOffer->getFieldH256(sfSwapID);
auto oppOfferKeylet = ripple::keylet::unchecked(sealedID);
auto sleSealedOffer = sb.peek(oppOfferKeylet);
if (!sleSealedOffer)
@@ -93,9 +93,9 @@ OptionExecute::doApply()
if (!sleOption)
return tecINTERNAL;
STAmount const strikePrice = sleOption->getFieldAmount(sfAmount);
STAmount const quantityShares = sleSealedOffer->getFieldAmount(sfAmount);
std::uint32_t const quantity = sleOptionOffer->getFieldU32(sfQualityIn);
STAmount const strikePrice = sleOption->getFieldAmount(sfStrikePrice);
STAmount const quantityShares = sleSealedOffer->getFieldAmount(sfLockedBalance);
std::uint32_t const quantity = sleOptionOffer->getFieldU32(sfQuantity);
STAmount const totalValue = STAmount(strikePrice.issue(), (strikePrice.mantissa() * quantity));
if (flags & tfOptionExpire)

View File

@@ -62,15 +62,15 @@ OptionList::doApply()
AccountID const srcAccID = ctx_.tx.getAccountID(sfAccount);
std::uint32_t const expiration = ctx_.tx.getFieldU32(sfExpiration);
STAmount const amount = ctx_.tx.getFieldAmount(sfAmount);
STAmount const strikePrice = ctx_.tx.getFieldAmount(sfStrikePrice);
auto sleSrcAcc = sb.peek(keylet::account(srcAccID));
if (!sleSrcAcc)
return terNO_ACCOUNT;
auto const optionKeylet = keylet::option(amount.getIssuer(), expiration);
auto const optionKeylet = keylet::option(strikePrice.getIssuer(), expiration);
auto const sleOption = std::make_shared<SLE>(optionKeylet);
(*sleOption)[sfAmount] = amount;
(*sleOption)[sfStrikePrice] = strikePrice;
(*sleOption)[sfExpiration] = expiration;
// apply

View File

@@ -410,6 +410,8 @@ extern SF_UINT32 const sfRewardLgrLast;
extern SF_UINT32 const sfFirstNFTokenSequence;
extern SF_UINT32 const sfImportSequence;
extern SF_UINT32 const sfXahauActivationLgrSeq;
extern SF_UINT32 const sfQuantity;
extern SF_UINT32 const sfToSeal;
// 64-bit integers (common)
extern SF_UINT64 const sfIndexNext;
@@ -483,6 +485,8 @@ extern SF_UINT256 const sfURITokenID;
extern SF_UINT256 const sfGovernanceFlags;
extern SF_UINT256 const sfGovernanceMarks;
extern SF_UINT256 const sfEmittedTxnID;
extern SF_UINT256 const sfOptionID;
extern SF_UINT256 const sfSwapID;
// currency amount (common)
extern SF_AMOUNT const sfAmount;
@@ -496,6 +500,7 @@ extern SF_AMOUNT const sfFee;
extern SF_AMOUNT const sfSendMax;
extern SF_AMOUNT const sfDeliverMin;
extern SF_AMOUNT const sfLockedBalance;
extern SF_AMOUNT const sfStrikePrice;
// currency amount (uncommon)
extern SF_AMOUNT const sfMinimumOffer;

View File

@@ -368,7 +368,7 @@ LedgerFormats::LedgerFormats()
add(jss::Option,
ltOPTION,
{
{sfAmount, soeREQUIRED},
{sfStrikePrice, soeREQUIRED},
{sfExpiration, soeREQUIRED},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED}
@@ -380,14 +380,14 @@ LedgerFormats::LedgerFormats()
{
{sfOwner, soeREQUIRED},
{sfOwnerNode, soeREQUIRED},
{sfOfferID, soeREQUIRED}, // OptionID
{sfAmount, soeREQUIRED}, // Locked Amount
{sfTakerPays, soeREQUIRED}, // Premium
{sfQualityIn, soeREQUIRED}, // Quantity
{sfQualityOut, soeREQUIRED}, // To Seal
{sfOptionID, soeREQUIRED}, // OptionID
{sfLockedBalance, soeREQUIRED}, // Locked Amount
{sfAmount, soeREQUIRED}, // Premium
{sfQuantity, soeREQUIRED}, // Quantity
{sfToSeal, soeREQUIRED}, // To Seal
{sfBookDirectory, soeREQUIRED},
{sfBookNode, soeREQUIRED},
{sfInvoiceID, soeOPTIONAL}, // MatchID
{sfSwapID, soeOPTIONAL}, // MatchID
{sfCheckID, soeOPTIONAL}, // SwapID
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED}

View File

@@ -157,6 +157,8 @@ CONSTRUCT_TYPED_SFIELD(sfLockCount, "LockCount", UINT32,
CONSTRUCT_TYPED_SFIELD(sfFirstNFTokenSequence, "FirstNFTokenSequence", UINT32, 50);
CONSTRUCT_TYPED_SFIELD(sfToSeal, "ToSeal", UINT32, 94);
CONSTRUCT_TYPED_SFIELD(sfQuantity, "Quantity", UINT32, 95);
CONSTRUCT_TYPED_SFIELD(sfXahauActivationLgrSeq, "XahauActivationLgrSeq",UINT32, 96);
CONSTRUCT_TYPED_SFIELD(sfImportSequence, "ImportSequence", UINT32, 97);
CONSTRUCT_TYPED_SFIELD(sfRewardTime, "RewardTime", UINT32, 98);
@@ -236,6 +238,8 @@ CONSTRUCT_TYPED_SFIELD(sfURITokenID, "URITokenID", UINT256,
CONSTRUCT_TYPED_SFIELD(sfGovernanceFlags, "GovernanceFlags", UINT256, 99);
CONSTRUCT_TYPED_SFIELD(sfGovernanceMarks, "GovernanceMarks", UINT256, 98);
CONSTRUCT_TYPED_SFIELD(sfEmittedTxnID, "EmittedTxnID", UINT256, 97);
CONSTRUCT_TYPED_SFIELD(sfOptionID, "OptionID", UINT256, 96);
CONSTRUCT_TYPED_SFIELD(sfSwapID, "SwapID", UINT256, 95);
// currency amount (common)
CONSTRUCT_TYPED_SFIELD(sfAmount, "Amount", AMOUNT, 1);
@@ -261,6 +265,7 @@ CONSTRUCT_TYPED_SFIELD(sfLockedBalance, "LockedBalance", AMOUNT,
CONSTRUCT_TYPED_SFIELD(sfBaseFeeDrops, "BaseFeeDrops", AMOUNT, 22);
CONSTRUCT_TYPED_SFIELD(sfReserveBaseDrops, "ReserveBaseDrops", AMOUNT, 23);
CONSTRUCT_TYPED_SFIELD(sfReserveIncrementDrops, "ReserveIncrementDrops", AMOUNT, 24);
CONSTRUCT_TYPED_SFIELD(sfStrikePrice, "StrikePrice", AMOUNT, 25);
// variable length (common)
CONSTRUCT_TYPED_SFIELD(sfPublicKey, "PublicKey", VL, 1);

View File

@@ -460,7 +460,7 @@ TxFormats::TxFormats()
add(jss::OptionList,
ttOPTION_LIST,
{
{sfAmount, soeREQUIRED},
{sfStrikePrice, soeREQUIRED},
{sfExpiration, soeREQUIRED},
{sfTicketSequence, soeOPTIONAL},
},
@@ -469,10 +469,10 @@ TxFormats::TxFormats()
add(jss::OptionCreate,
ttOPTION_CREATE,
{
{sfOfferID, soeREQUIRED}, // Option ID
{sfOptionID, soeREQUIRED}, // Option ID
{sfAmount, soeREQUIRED}, // Premium
{sfQualityIn, soeREQUIRED}, // Quantity
{sfInvoiceID, soeOPTIONAL}, // Swap ID
{sfQuantity, soeREQUIRED}, // Quantity
{sfSwapID, soeOPTIONAL}, // Swap ID
{sfTicketSequence, soeOPTIONAL},
},
commonFields);
@@ -480,8 +480,8 @@ TxFormats::TxFormats()
add(jss::OptionExecute,
ttOPTION_EXECUTE,
{
{sfOfferID, soeREQUIRED},
{sfInvoiceID, soeOPTIONAL},
{sfOptionID, soeREQUIRED},
{sfSwapID, soeOPTIONAL},
{sfTicketSequence, soeOPTIONAL},
},
commonFields);

View File

@@ -58,8 +58,8 @@ struct Option_test : public beast::unit_test::suite
std::uint32_t const& seq)
{
auto const sle = env.le(keylet::optionOffer(account, seq));
if (sle->isFieldPresent(sfAmount))
return (*sle)[sfAmount];
if (sle->isFieldPresent(sfLockedBalance))
return (*sle)[sfLockedBalance];
return STAmount(0);
}
@@ -67,13 +67,13 @@ struct Option_test : public beast::unit_test::suite
optionlist(
jtx::Account const& account,
std::uint32_t expiration,
STAmount const& amount)
STAmount const& strikePrice)
{
using namespace jtx;
Json::Value jv;
jv[jss::TransactionType] = jss::OptionList;
jv[jss::Account] = account.human();
jv[jss::Amount] = amount.getJson(JsonOptions::none);
jv[sfStrikePrice.jsonName] = strikePrice.getJson(JsonOptions::none);
jv[sfExpiration.jsonName] = expiration;
return jv;
}
@@ -83,15 +83,15 @@ struct Option_test : public beast::unit_test::suite
jtx::Account const& account,
uint256 const& optionId,
uint32_t const& quantity,
STAmount const& amount)
STAmount const& premium)
{
using namespace jtx;
Json::Value jv;
jv[jss::TransactionType] = jss::OptionCreate;
jv[jss::Account] = account.human();
jv[sfOfferID.jsonName] = to_string(optionId);
jv[jss::Amount] = amount.getJson(JsonOptions::none);
jv[sfQualityIn.jsonName] = quantity;
jv[sfOptionID.jsonName] = to_string(optionId);
jv[jss::Amount] = premium.getJson(JsonOptions::none);
jv[sfQuantity.jsonName] = quantity;
return jv;
}
@@ -105,8 +105,8 @@ struct Option_test : public beast::unit_test::suite
Json::Value jv;
jv[jss::TransactionType] = jss::OptionExecute;
jv[jss::Account] = account.human();
jv[sfOfferID.jsonName] = to_string(optionId);
jv[sfInvoiceID.jsonName] = to_string(offerId);
jv[sfOptionID.jsonName] = to_string(optionId);
jv[sfSwapID.jsonName] = to_string(offerId);
;
return jv;
}
@@ -125,6 +125,33 @@ struct Option_test : public beast::unit_test::suite
return keylet::optionOffer(account, sequence).key;
}
static auto
getOptionList(
jtx::Env& env,
AccountID const& issuer)
{
Json::Value jvbp;
jvbp[jss::ledger_index] = "current";
jvbp[jss::account] = to_string(issuer);
jvbp[jss::type] = "option";
return env.rpc("json", "account_objects", to_string(jvbp))[jss::result];
}
static auto
getOptionBookOffers(
jtx::Env& env,
STAmount const& strike_price,
std::uint32_t expiration)
{
Json::Value jvbp;
jvbp[jss::ledger_index] = "current";
jvbp[jss::strike_price][jss::currency] = to_string(strike_price.issue().currency);
jvbp[jss::strike_price][jss::issuer] = to_string(strike_price.issue().account);
jvbp[jss::strike_price][jss::value] = to_string(strike_price.mantissa());
jvbp[jss::expiration] = to_string(expiration);
return env.rpc("json", "option_book_offers", to_string(jvbp))[jss::result];
}
void
testBookBuy(FeatureBitset features)
{
@@ -364,7 +391,7 @@ struct Option_test : public beast::unit_test::suite
// network::makeNetworkConfig(21337),
// features,
// nullptr,
// beast::severities::kWarning};
// beast::severities::kTrace};
auto const feeDrops = env.current()->fees().base;
@@ -408,6 +435,9 @@ struct Option_test : public beast::unit_test::suite
BEAST_EXPECT(
lockedValue(env, writer, seq) == XRP(quantity));
auto jrr = getOptionBookOffers(env, XRP(strikePrice), expiration);
std::cout << "RESULT: " << jrr << "\n";
preWriter = env.balance(writer);
preBuyer = env.balance(buyer);
@@ -428,6 +458,9 @@ struct Option_test : public beast::unit_test::suite
preWriter = env.balance(writer);
preBuyer = env.balance(buyer);
auto jrr1 = getOptionBookOffers(env, XRP(strikePrice), expiration);
std::cout << "RESULT1: " << jrr1 << "\n";
// Execute Option
env(optionexecute(buyer, optionId, offerId), ter(tesSUCCESS));
env.close();
@@ -438,6 +471,11 @@ struct Option_test : public beast::unit_test::suite
BEAST_EXPECT(
env.balance(writer) ==
preWriter + XRP(quantity * strikePrice));
auto jrrList = getOptionList(env, zeroAcct);
std::cout << "RESULT LIST: " << jrrList << "\n";
auto jrr2 = getOptionBookOffers(env, XRP(strikePrice), expiration);
std::cout << "RESULT2: " << jrr2 << "\n";
}
public: