rippled
Loading...
Searching...
No Matches
NFTokenCancelOffer.cpp
1#include <xrpld/app/tx/detail/NFTokenCancelOffer.h>
2#include <xrpld/app/tx/detail/NFTokenUtils.h>
3
4#include <xrpl/ledger/View.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/TxFlags.h>
7
8#include <boost/endian/conversion.hpp>
9
10namespace xrpl {
11
17
20{
21 if (auto const& ids = ctx.tx[sfNFTokenOffers]; ids.empty() || (ids.size() > maxTokenOfferCancelCount))
22 return temMALFORMED;
23
24 // In order to prevent unnecessarily overlarge transactions, we
25 // disallow duplicates in the list of offers to cancel.
26 STVector256 ids = ctx.tx.getFieldV256(sfNFTokenOffers);
27 std::sort(ids.begin(), ids.end());
28 if (std::adjacent_find(ids.begin(), ids.end()) != ids.end())
29 return temMALFORMED;
30
31 return tesSUCCESS;
32}
33
34TER
36{
37 auto const account = ctx.tx[sfAccount];
38
39 auto const& ids = ctx.tx[sfNFTokenOffers];
40
41 auto ret = std::find_if(ids.begin(), ids.end(), [&ctx, &account](uint256 const& id) {
42 auto const offer = ctx.view.read(keylet::child(id));
43
44 // If id is not in the ledger we assume the offer was consumed
45 // before we got here.
46 if (!offer)
47 return false;
48
49 // If id is in the ledger but is not an NFTokenOffer, then
50 // they have no permission.
51 if (offer->getType() != ltNFTOKEN_OFFER)
52 return true;
53
54 // Anyone can cancel, if expired
55 if (hasExpired(ctx.view, (*offer)[~sfExpiration]))
56 return false;
57
58 // The owner can always cancel
59 if ((*offer)[sfOwner] == account)
60 return false;
61
62 // The recipient can always cancel
63 if (auto const dest = (*offer)[~sfDestination]; dest == account)
64 return false;
65
66 return true;
67 });
68
69 if (ret != ids.end())
70 return tecNO_PERMISSION;
71
72 return tesSUCCESS;
73}
74
75TER
77{
78 for (auto const& id : ctx_.tx[sfNFTokenOffers])
79 {
80 if (auto offer = view().peek(keylet::nftoffer(id)); offer && !nft::deleteTokenOffer(view(), offer))
81 {
82 // LCOV_EXCL_START
83 JLOG(j_.fatal()) << "Unable to delete token offer " << id << " (ledger " << view().seq() << ")";
84 return tefBAD_LEDGER;
85 // LCOV_EXCL_STOP
86 }
87 }
88
89 return tesSUCCESS;
90}
91
92} // namespace xrpl
T adjacent_find(T... args)
Stream fatal() const
Definition Journal.h:324
STTx const & tx
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
static NotTEC preflight(PreflightContext const &ctx)
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
LedgerIndex seq() const
Returns the sequence number of the base ledger.
Definition ReadView.h:97
STVector256 const & getFieldV256(SField const &field) const
Definition STObject.cpp:646
std::vector< uint256 >::iterator begin()
std::vector< uint256 >::iterator end()
beast::Journal const j_
Definition Transactor.h:110
ApplyView & view()
Definition Transactor.h:128
ApplyContext & ctx_
Definition Transactor.h:108
T find_if(T... args)
Keylet nftoffer(AccountID const &owner, std::uint32_t seq)
An offer from an account to buy or sell an NFT.
Definition Indexes.cpp:375
bool deleteTokenOffer(ApplyView &view, std::shared_ptr< SLE > const &offer)
Deletes the given token offer.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
@ tefBAD_LEDGER
Definition TER.h:150
constexpr std::uint32_t const tfNFTokenCancelOfferMask
Definition TxFlags.h:215
@ temMALFORMED
Definition TER.h:67
@ tecNO_PERMISSION
Definition TER.h:286
@ tesSUCCESS
Definition TER.h:225
std::size_t constexpr maxTokenOfferCancelCount
The maximum number of token offers that can be canceled at once.
Definition Protocol.h:52
T sort(T... args)
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:53
State information when preflighting a tx.
Definition Transactor.h:15