1#include <xrpld/app/ledger/LedgerMaster.h>
2#include <xrpld/app/ledger/OrderBookDBImpl.h>
4#include <xrpl/core/JobQueue.h>
5#include <xrpl/protocol/Indexes.h>
6#include <xrpl/server/NetworkOPs.h>
7#include <xrpl/tx/transactors/dex/AMMUtils.h>
13 , pathSearchMax_(config.pathSearchMax)
14 , standalone_(config.standalone)
16 , j_(registry.getJournal(
"OrderBookDB"))
31 JLOG(
j_.
warn()) <<
"Eliding full order book update: no ledger";
39 if ((ledger->seq() > seq) && ((ledger->seq() - seq) < 25600))
42 if ((ledger->seq() <= seq) && ((seq - ledger->seq()) < 16))
49 JLOG(
j_.
debug()) <<
"Full order book update: " << seq <<
" to " << ledger->seq();
76 if (
auto const seq =
seq_.
load(); seq > ledger->seq())
78 JLOG(
j_.
debug()) <<
"Eliding update for " << ledger->seq()
79 <<
" because of pending update to later " << seq;
91 JLOG(
j_.
debug()) <<
"Beginning update (" << ledger->seq() <<
")";
98 for (
auto& sle : ledger->sles)
102 JLOG(
j_.
info()) <<
"Update halted because the process is stopping";
107 if (sle->getType() == ltDIR_NODE && sle->isFieldPresent(sfExchangeRate) &&
108 sle->getFieldH256(sfRootIndex) == sle->key())
112 book.
in.
currency = sle->getFieldH160(sfTakerPaysCurrency);
113 book.
in.
account = sle->getFieldH160(sfTakerPaysIssuer);
114 book.
out.
currency = sle->getFieldH160(sfTakerGetsCurrency);
115 book.
out.
account = sle->getFieldH160(sfTakerGetsIssuer);
116 book.
domain = (*sle)[~sfDomainID];
120 domainBooks[{book.
in, *book.
domain}].insert(book.
out);
124 allBooks[book.
in].insert(book.
out);
129 xrpDomainBooks.insert({book.
in, *book.
domain});
133 xrpBooks.insert(book.
in);
138 else if (sle->getType() == ltAMM)
140 auto const issue1 = (*sle)[sfAsset].get<
Issue>();
141 auto const issue2 = (*sle)[sfAsset2].get<
Issue>();
143 allBooks[
in].insert(
out);
150 addBook(issue1, issue2);
151 addBook(issue2, issue1);
157 JLOG(
j_.
info()) <<
"Missing node in " << ledger->seq() <<
" during update: " << mn.
what();
162 JLOG(
j_.
debug()) <<
"Update completed (" << ledger->seq() <<
"): " << cnt <<
" books found";
172 registry_.get().getLedgerMaster().newOrderBookDB();
210 auto getBooks = [&](
auto const& container,
auto const& key) {
211 if (
auto it = container.find(key); it != container.end())
213 auto const& books = it->second;
216 for (
auto const& gets : books)
242 return static_cast<int>(it->second.size());
247 return static_cast<int>(it->second.size());
275 "xrpl::OrderBookDB::makeBookListeners : result roundtrip "
316 if (node.getFieldU16(sfLedgerEntryType) == ltOFFER)
318 auto process = [&,
this](
SField const& field) {
319 if (
auto data =
dynamic_cast<STObject const*
>(node.peekAtPField(field)); data &&
320 data->isFieldPresent(sfTakerPays) && data->isFieldPresent(sfTakerGets))
323 {data->getFieldAmount(sfTakerGets).issue(),
324 data->getFieldAmount(sfTakerPays).issue(),
325 (*data)[~sfDomainID]});
327 listeners->publish(jvObj, havePublished);
333 if (node.getFName() == sfModifiedNode)
335 process(sfPreviousFields);
337 else if (node.getFName() == sfCreatedNode)
339 process(sfNewFields);
341 else if (node.getFName() == sfDeletedNode)
343 process(sfFinalFields);
349 JLOG(
j_.
info()) <<
"processTxn: field not found (" << ex.
what() <<
")";
A transaction that is in a closed ledger.
TxMeta const & getMeta() const
std::optional< uint256 > domain
A currency issued by an account.
hardened_hash_map< std::pair< Issue, Domain >, hardened_hash_set< Issue > > domainBooks_
void addOrderBook(Book const &book) override
Add an order book to track.
BookListeners::pointer makeBookListeners(Book const &) override
Create a new book listeners for a book.
BookListeners::pointer getBookListeners(Book const &) override
Get the book listeners for a book.
BookToListenersMap mListeners
int getBookSize(Issue const &issue, std::optional< Domain > const &domain=std::nullopt) override
Get the count of order books that want a specific issue.
hash_set< Issue > xrpBooks_
void setup(std::shared_ptr< ReadView const > const &ledger) override
Initialize or update the order book database with a new ledger.
hash_set< std::pair< Issue, Domain > > xrpDomainBooks_
OrderBookDBImpl(ServiceRegistry ®istry, OrderBookDBConfig const &config)
hardened_hash_map< Issue, hardened_hash_set< Issue > > allBooks_
std::atomic< std::uint32_t > seq_
void processTxn(std::shared_ptr< ReadView const > const &ledger, AcceptedLedgerTx const &alTx, MultiApiJson const &jvObj) override
Process a transaction for order book tracking.
std::vector< Book > getBooksByTakerPays(Issue const &issue, std::optional< Domain > const &domain=std::nullopt) override
Get all order books that want a specific issue.
void update(std::shared_ptr< ReadView const > const &ledger)
bool isBookToXRP(Issue const &issue, std::optional< Domain > const &domain=std::nullopt) override
Check if an order book to XRP exists for the given issue.
std::reference_wrapper< ServiceRegistry > registry_
std::recursive_mutex mLock
Service registry for dependency injection.
T emplace_back(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool isXRP(AccountID const &c)
std::unique_ptr< OrderBookDB > make_OrderBookDB(ServiceRegistry ®istry, OrderBookDBConfig const &config)
Create an OrderBookDB instance.
Configuration for OrderBookDB.