xrpld
Loading...
Searching...
No Matches
Unsubscribe.cpp
1#include <xrpld/rpc/Context.h>
2#include <xrpld/rpc/Role.h>
3#include <xrpld/rpc/detail/RPCHelpers.h>
4
5#include <xrpl/basics/Log.h>
6#include <xrpl/basics/base_uint.h>
7#include <xrpl/json/json_value.h>
8#include <xrpl/protocol/AccountID.h>
9#include <xrpl/protocol/Book.h>
10#include <xrpl/protocol/ErrorCodes.h>
11#include <xrpl/protocol/RPCErr.h>
12#include <xrpl/protocol/jss.h>
13#include <xrpl/server/InfoSub.h>
14#include <xrpl/server/NetworkOPs.h>
15
16#include <string>
17
18namespace xrpl {
19
20json::Value
22{
23 InfoSub::pointer ispSub;
25 bool removeUrl{false};
26
27 if (!context.infoSub && !context.params.isMember(jss::url))
28 {
29 // Must be a JSON-RPC call.
31 }
32
33 if (context.params.isMember(jss::url))
34 {
35 if (context.role != Role::ADMIN)
37
38 std::string const strUrl = context.params[jss::url].asString();
39 ispSub = context.netOps.findRpcSub(strUrl);
40 if (!ispSub)
41 return jvResult;
42 removeUrl = true;
43 }
44 else
45 {
46 ispSub = context.infoSub;
47 }
48
49 if (context.params.isMember(jss::streams))
50 {
51 if (!context.params[jss::streams].isArray())
53
54 for (auto& it : context.params[jss::streams])
55 {
56 if (!it.isString())
58
59 std::string const streamName = it.asString();
60 if (streamName == "server")
61 {
62 context.netOps.unsubServer(ispSub->getSeq());
63 }
64 else if (streamName == "ledger")
65 {
66 context.netOps.unsubLedger(ispSub->getSeq());
67 }
68 else if (streamName == "manifests")
69 {
70 context.netOps.unsubManifests(ispSub->getSeq());
71 }
72 else if (streamName == "transactions")
73 {
74 context.netOps.unsubTransactions(ispSub->getSeq());
75 }
76 else if (
77 streamName == "transactions_proposed" ||
78 streamName == "rt_transactions") // DEPRECATED
79 {
80 context.netOps.unsubRTTransactions(ispSub->getSeq());
81 }
82 else if (streamName == "validations")
83 {
84 context.netOps.unsubValidations(ispSub->getSeq());
85 }
86 else if (streamName == "peer_status")
87 {
88 context.netOps.unsubPeerStatus(ispSub->getSeq());
89 }
90 else if (streamName == "consensus")
91 {
92 context.netOps.unsubConsensus(ispSub->getSeq());
93 }
94 else
95 {
97 }
98 }
99 }
100
101 auto accountsProposed = context.params.isMember(jss::accounts_proposed)
102 ? jss::accounts_proposed
103 : jss::rt_accounts; // DEPRECATED
104 if (context.params.isMember(accountsProposed))
105 {
106 if (!context.params[accountsProposed].isArray())
108
109 auto ids = RPC::parseAccountIds(context.params[accountsProposed]);
110 if (ids.empty())
112 context.netOps.unsubAccount(ispSub, ids, true);
113 }
114
115 if (context.params.isMember(jss::accounts))
116 {
117 if (!context.params[jss::accounts].isArray())
119
120 auto ids = RPC::parseAccountIds(context.params[jss::accounts]);
121 if (ids.empty())
123 context.netOps.unsubAccount(ispSub, ids, false);
124 }
125
126 if (context.params.isMember(jss::account_history_tx_stream))
127 {
128 auto const& req = context.params[jss::account_history_tx_stream];
129 if (!req.isMember(jss::account) || !req[jss::account].isString())
131
132 auto const id = parseBase58<AccountID>(req[jss::account].asString());
133 if (!id)
135
136 bool stopHistoryOnly = false;
137 if (req.isMember(jss::stop_history_tx_only))
138 {
139 if (!req[jss::stop_history_tx_only].isBool())
141 stopHistoryOnly = req[jss::stop_history_tx_only].asBool();
142 }
143 context.netOps.unsubAccountHistory(ispSub, *id, stopHistoryOnly);
144
145 JLOG(context.j.debug()) << "doUnsubscribe: account_history_tx_stream: " << toBase58(*id)
146 << " stopHistoryOnly=" << (stopHistoryOnly ? "true" : "false");
147 }
148
149 if (context.params.isMember(jss::books))
150 {
151 if (!context.params[jss::books].isArray())
153
154 for (auto& jv : context.params[jss::books])
155 {
156 if (!jv.isObject() || !jv.isMember(jss::taker_pays) || !jv.isMember(jss::taker_gets) ||
157 !jv[jss::taker_pays].isObjectOrNull() || !jv[jss::taker_gets].isObjectOrNull())
158 {
160 }
161
162 Book book;
163
164 if (auto const err = RPC::parseSubUnsubJson(book.in, jv, jss::taker_pays, context.j);
165 err != RpcSuccess)
166 return rpcError(err);
167
168 if (auto const err = RPC::parseSubUnsubJson(book.out, jv, jss::taker_gets, context.j);
169 err != RpcSuccess)
170 return rpcError(err);
171
172 if (book.in == book.out)
173 {
174 JLOG(context.j.info()) << "taker_gets same as taker_pays.";
175 return rpcError(RpcBadMarket);
176 }
177
178 if (jv.isMember(jss::domain))
179 {
180 uint256 domain;
181 if (!jv[jss::domain].isString() || !domain.parseHex(jv[jss::domain].asString()))
182 {
184 }
185
186 book.domain = domain;
187 }
188
189 if (!context.netOps.unsubBook(ispSub, book))
190 {
191 JLOG(context.j.debug())
192 << "doUnsubscribe: book not subscribed (no-op for seq=" << ispSub->getSeq()
193 << ")";
194 }
195
196 // both_sides is deprecated.
197 if ((jv.isMember(jss::both) && jv[jss::both].asBool()) ||
198 (jv.isMember(jss::both_sides) && jv[jss::both_sides].asBool()))
199 {
200 if (!context.netOps.unsubBook(ispSub, reversed(book)))
201 {
202 JLOG(context.j.debug())
203 << "doUnsubscribe: reversed book not subscribed (no-op for seq="
204 << ispSub->getSeq() << ")";
205 }
206 }
207 }
208 }
209
210 if (removeUrl)
211 {
212 context.netOps.tryRemoveRpcSub(context.params[jss::url].asString());
213 }
214
215 return jvResult;
216}
217
218} // namespace xrpl
Stream debug() const
Definition Journal.h:297
Stream info() const
Definition Journal.h:303
Represents a JSON value.
Definition json_value.h:130
bool isArray() const
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:507
Specifies an order book.
Definition Book.h:16
virtual bool unsubRTTransactions(std::uint64_t uListener)=0
virtual bool unsubConsensus(std::uint64_t uListener)=0
virtual bool unsubTransactions(std::uint64_t uListener)=0
virtual bool unsubServer(std::uint64_t uListener)=0
virtual bool tryRemoveRpcSub(std::string const &strUrl)=0
virtual void unsubAccountHistory(ref ispListener, AccountID const &account, bool historyOnly)=0
unsubscribe an account's transactions
virtual bool unsubBook(ref ispListener, Book const &)=0
Remove a book subscription for a live subscriber.
virtual bool unsubLedger(std::uint64_t uListener)=0
virtual bool unsubPeerStatus(std::uint64_t uListener)=0
virtual bool unsubManifests(std::uint64_t uListener)=0
virtual bool unsubValidations(std::uint64_t uListener)=0
virtual pointer findRpcSub(std::string const &strUrl)=0
virtual void unsubAccount(ref isplistener, hash_set< AccountID > const &vnaAccountIDs, bool realTime)=0
std::shared_ptr< InfoSub > pointer
Definition InfoSub.h:47
std::uint64_t getSeq() const
Definition InfoSub.cpp:114
@ Object
object value (collection of name/value pairs).
Definition json_value.h:26
hash_set< AccountID > parseAccountIds(json::Value const &jvArray)
Parses an array of account IDs from a JSON value.
ErrorCodeI parseSubUnsubJson(Asset &asset, json::Value const &params, json::StaticString const &name, beast::Journal j)
Parse subscribe/unsubscribe parameters.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
@ RpcStreamMalformed
Definition ErrorCodes.h:108
@ RpcBadMarket
Definition ErrorCodes.h:79
@ RpcSuccess
Definition ErrorCodes.h:26
@ RpcActMalformed
Definition ErrorCodes.h:72
@ RpcDomainMalformed
Definition ErrorCodes.h:140
@ RpcInvalidParams
Definition ErrorCodes.h:66
@ RpcNoPermission
Definition ErrorCodes.h:35
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:93
json::Value rpcError(ErrorCodeI iError)
Definition RPCErr.cpp:13
@ ADMIN
Definition Role.h:24
Book reversed(Book const &book)
Definition Book.cpp:30
json::Value doUnsubscribe(RPC::JsonContext &)
BaseUInt< 256 > uint256
Definition base_uint.h:562
beast::Journal const j
Definition Context.h:20
InfoSub::pointer infoSub
Definition Context.h:28
NetworkOPs & netOps
Definition Context.h:23
json::Value params
Definition Context.h:43