mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-03 17:35:51 +00:00
Recognize ripplerpc 2.0 requests and respond in kind:
* Force jtx to request/receive the 2.0 API * Force the JSON and WebSocket tests to use 2.0 API * This specifically allows the Websocket to create 2.0 json/ripple and get back a 2.0 response. * Add test for malformed json2 * Add check for parse failure * Add check for params to be in array form. * Correct type-o discovered in tests due to stricter checking. * Add API version to the WSClient & JSONRPCClient test * Update source.dox with more headers
This commit is contained in:
committed by
Nik Bougalis
parent
cdf470e68d
commit
2fd0540ed4
@@ -105,6 +105,10 @@ WARN_LOGFILE =
|
||||
INPUT = \
|
||||
\
|
||||
../src/ripple/protocol/STObject.h \
|
||||
../src/ripple/protocol/JsonFields.h \
|
||||
../src/ripple/test/AbstractClient.h \
|
||||
../src/ripple/test/JSONRPCClient.h \
|
||||
../src/ripple/test/WSClient.h \
|
||||
|
||||
|
||||
INPUT_ENCODING = UTF-8
|
||||
|
||||
@@ -434,8 +434,8 @@ int PathRequest::parseJson (Json::Value const& jvParams)
|
||||
}
|
||||
}
|
||||
|
||||
if (jvParams.isMember ("id"))
|
||||
jvId = jvParams["id"];
|
||||
if (jvParams.isMember (jss::id))
|
||||
jvId = jvParams[jss::id];
|
||||
|
||||
return PFR_PJ_NOCHANGE;
|
||||
}
|
||||
@@ -649,7 +649,7 @@ Json::Value PathRequest::doUpdate(
|
||||
newStatus[jss::full_reply] = ! fast;
|
||||
|
||||
if (jvId)
|
||||
newStatus["id"] = jvId;
|
||||
newStatus[jss::id] = jvId;
|
||||
|
||||
bool loaded = app_.getFeeTrack().isLoadedLocal();
|
||||
|
||||
|
||||
@@ -487,7 +487,7 @@ private:
|
||||
if (!jvRequest.isObject ())
|
||||
return rpcError (rpcINVALID_PARAMS);
|
||||
|
||||
jvRequest["method"] = jvParams[0u];
|
||||
jvRequest[jss::method] = jvParams[0u];
|
||||
|
||||
return jvRequest;
|
||||
}
|
||||
@@ -495,6 +495,53 @@ private:
|
||||
return rpcError (rpcINVALID_PARAMS);
|
||||
}
|
||||
|
||||
bool isValidJson2(Json::Value const& jv)
|
||||
{
|
||||
if (jv.isObject())
|
||||
{
|
||||
if (jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0" &&
|
||||
jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0" &&
|
||||
jv.isMember(jss::id) && jv.isMember(jss::method))
|
||||
{
|
||||
if (jv.isMember(jss::params) &&
|
||||
!(jv[jss::params].isArray() || jv[jss::params].isNull()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Json::Value parseJson2(Json::Value const& jvParams)
|
||||
{
|
||||
Json::Reader reader;
|
||||
Json::Value jv;
|
||||
bool valid_parse = reader.parse(jvParams[0u].asString(), jv);
|
||||
if (valid_parse && isValidJson2(jv))
|
||||
{
|
||||
Json::Value jv1{Json::objectValue};
|
||||
if (jv.isMember(jss::params))
|
||||
{
|
||||
auto const& params = jv[jss::params][0u];
|
||||
for (auto i = params.begin(); i != params.end(); ++i)
|
||||
jv1[i.key().asString()] = *i;
|
||||
}
|
||||
jv1[jss::jsonrpc] = jv[jss::jsonrpc];
|
||||
jv1[jss::ripplerpc] = jv[jss::ripplerpc];
|
||||
jv1[jss::id] = jv[jss::id];
|
||||
jv1[jss::method] = jv[jss::method];
|
||||
return jv1;
|
||||
}
|
||||
auto jv_error = rpcError(rpcINVALID_PARAMS);
|
||||
if (jv.isMember(jss::jsonrpc))
|
||||
jv_error[jss::jsonrpc] = jv[jss::jsonrpc];
|
||||
if (jv.isMember(jss::ripplerpc))
|
||||
jv_error[jss::ripplerpc] = jv[jss::ripplerpc];
|
||||
if (jv.isMember(jss::id))
|
||||
jv_error[jss::id] = jv[jss::id];
|
||||
return jv_error;
|
||||
}
|
||||
|
||||
// ledger [id|index|current|closed|validated] [full|tx]
|
||||
Json::Value parseLedger (Json::Value const& jvParams)
|
||||
{
|
||||
@@ -1003,6 +1050,7 @@ public:
|
||||
{ "gateway_balances", &RPCParser::parseGatewayBalances , 1, -1 },
|
||||
{ "get_counts", &RPCParser::parseGetCounts, 0, 1 },
|
||||
{ "json", &RPCParser::parseJson, 2, 2 },
|
||||
{ "json2", &RPCParser::parseJson2, 1, 1 },
|
||||
{ "ledger", &RPCParser::parseLedger, 0, 2 },
|
||||
{ "ledger_accept", &RPCParser::parseAsIs, 0, 0 },
|
||||
{ "ledger_closed", &RPCParser::parseAsIs, 0, 0 },
|
||||
@@ -1181,7 +1229,7 @@ rpcCmdLineToJson (std::vector<std::string> const& args,
|
||||
|
||||
retParams = Json::Value (Json::objectValue);
|
||||
|
||||
retParams["method"] = args[0];
|
||||
retParams[jss::method] = args[0];
|
||||
retParams[jss::params] = jvRpcParams;
|
||||
|
||||
jvRequest = rpParser.parseCommand (args[0], jvRpcParams, true);
|
||||
@@ -1210,6 +1258,12 @@ cmdLineToJSONRPC (std::vector<std::string> const& args, beast::Journal j)
|
||||
auto& paramsArray = Json::setArray (jv, jss::params);
|
||||
paramsArray.append (paramsObj);
|
||||
}
|
||||
if (paramsObj.isMember(jss::jsonrpc))
|
||||
jv[jss::jsonrpc] = paramsObj[jss::jsonrpc];
|
||||
if (paramsObj.isMember(jss::ripplerpc))
|
||||
jv[jss::ripplerpc] = paramsObj[jss::ripplerpc];
|
||||
if (paramsObj.isMember(jss::id))
|
||||
jv[jss::id] = paramsObj[jss::id];
|
||||
return jv;
|
||||
}
|
||||
|
||||
@@ -1267,6 +1321,12 @@ rpcClient(std::vector<std::string> const& args,
|
||||
|
||||
jvParams.append (jvRequest);
|
||||
|
||||
if (jvRequest.isMember(jss::params))
|
||||
{
|
||||
auto const& params = jvRequest[jss::params];
|
||||
assert(params.size() == 1);
|
||||
jvParams.append(params[0u]);
|
||||
}
|
||||
{
|
||||
boost::asio::io_service isService;
|
||||
RPCCall::fromNetwork (
|
||||
@@ -1276,8 +1336,8 @@ rpcClient(std::vector<std::string> const& args,
|
||||
setup.client.user,
|
||||
setup.client.password,
|
||||
"",
|
||||
jvRequest.isMember ("method") // Allow parser to rewrite method.
|
||||
? jvRequest["method"].asString () : args[0],
|
||||
jvRequest.isMember (jss::method) // Allow parser to rewrite method.
|
||||
? jvRequest[jss::method].asString () : args[0],
|
||||
jvParams, // Parsed, execute.
|
||||
setup.client.secure != 0, // Use SSL
|
||||
config.quiet(),
|
||||
@@ -1331,6 +1391,13 @@ rpcClient(std::vector<std::string> const& args,
|
||||
nRet = rpcINTERNAL;
|
||||
}
|
||||
|
||||
if (jvRequest.isMember(jss::jsonrpc))
|
||||
jvOutput[jss::jsonrpc] = jvRequest[jss::jsonrpc];
|
||||
if (jvRequest.isMember(jss::ripplerpc))
|
||||
jvOutput[jss::ripplerpc] = jvRequest[jss::ripplerpc];
|
||||
if (jvRequest.isMember(jss::id))
|
||||
jvOutput[jss::id] = jvRequest[jss::id];
|
||||
|
||||
return { nRet, std::move(jvOutput) };
|
||||
}
|
||||
|
||||
|
||||
@@ -213,6 +213,7 @@ JSS ( ip ); // in: Connect, out: OverlayImpl
|
||||
JSS ( issuer ); // in: RipplePathFind, Subscribe,
|
||||
// Unsubscribe, BookOffers
|
||||
// out: paths/Node, STPathSet, STAmount
|
||||
JSS ( jsonrpc ); // json version
|
||||
JSS ( key ); // out: WalletSeed
|
||||
JSS ( key_type ); // in/out: WalletPropose, TransactionSign
|
||||
JSS ( latency ); // out: PeerImp
|
||||
@@ -350,6 +351,7 @@ JSS ( response ); // websocket
|
||||
JSS ( result ); // RPC
|
||||
JSS ( ripple_lines ); // out: NetworkOPs
|
||||
JSS ( ripple_state ); // in: LedgerEntr
|
||||
JSS ( ripplerpc ); // ripple RPC version
|
||||
JSS ( role ); // out: Ping.cpp
|
||||
JSS ( rt_accounts ); // in: Subscribe, Unsubscribe
|
||||
JSS ( sanity ); // out: PeerImp
|
||||
|
||||
@@ -124,10 +124,18 @@ error_code_i fillHandler (Context& context,
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.params.isMember ("command"))
|
||||
if (!context.params.isMember(jss::command) && !context.params.isMember(jss::method))
|
||||
return rpcCOMMAND_MISSING;
|
||||
if (context.params.isMember(jss::command) && context.params.isMember(jss::method))
|
||||
{
|
||||
if (context.params[jss::command].asString() !=
|
||||
context.params[jss::method].asString())
|
||||
return rpcUNKNOWN_COMMAND;
|
||||
}
|
||||
|
||||
std::string strCommand = context.params[jss::command].asString ();
|
||||
std::string strCommand = context.params.isMember(jss::command) ?
|
||||
context.params[jss::command].asString() :
|
||||
context.params[jss::method].asString();
|
||||
|
||||
JLOG (context.j.trace()) << "COMMAND:" << strCommand;
|
||||
JLOG (context.j.trace()) << "REQUEST:" << context.params;
|
||||
|
||||
@@ -404,7 +404,9 @@ ServerHandlerImp::processSession(
|
||||
|
||||
// Requests without "command" are invalid.
|
||||
Json::Value jr(Json::objectValue);
|
||||
if (! jv.isMember (jss::command))
|
||||
if ((!jv.isMember(jss::command) && !jv.isMember(jss::method)) ||
|
||||
(jv.isMember(jss::command) && jv.isMember(jss::method) &&
|
||||
jv[jss::command].asString() != jv[jss::method].asString()))
|
||||
{
|
||||
jr[jss::type] = jss::response;
|
||||
jr[jss::status] = jss::error;
|
||||
@@ -412,13 +414,19 @@ ServerHandlerImp::processSession(
|
||||
jr[jss::request] = jv;
|
||||
if (jv.isMember (jss::id))
|
||||
jr[jss::id] = jv[jss::id];
|
||||
if (jv.isMember(jss::jsonrpc))
|
||||
jr[jss::jsonrpc] = jv[jss::jsonrpc];
|
||||
if (jv.isMember(jss::jsonrpc))
|
||||
jr[jss::ripplerpc] = jv[jss::ripplerpc];
|
||||
|
||||
is->getConsumer().charge(Resource::feeInvalidRPC);
|
||||
return jr;
|
||||
}
|
||||
|
||||
Resource::Charge loadType = Resource::feeReferenceRPC;
|
||||
auto required = RPC::roleRequired(jv[jss::command].asString());
|
||||
auto required = RPC::roleRequired(jv.isMember(jss::command) ?
|
||||
jv[jss::command].asString() :
|
||||
jv[jss::method].asString());
|
||||
auto role = requestRole(
|
||||
required,
|
||||
session->port(),
|
||||
@@ -475,6 +483,10 @@ ServerHandlerImp::processSession(
|
||||
|
||||
if (jv.isMember(jss::id))
|
||||
jr[jss::id] = jv[jss::id];
|
||||
if (jv.isMember(jss::jsonrpc))
|
||||
jr[jss::jsonrpc] = jv[jss::jsonrpc];
|
||||
if (jv.isMember(jss::jsonrpc))
|
||||
jr[jss::ripplerpc] = jv[jss::ripplerpc];
|
||||
jr[jss::type] = jss::response;
|
||||
return jr;
|
||||
}
|
||||
@@ -539,8 +551,8 @@ ServerHandlerImp::processRequest (Port const& port,
|
||||
//
|
||||
// VFALCO NOTE Except that "id" isn't included in the following errors.
|
||||
//
|
||||
Json::Value const& id = jsonRPC ["id"];
|
||||
Json::Value const& method = jsonRPC ["method"];
|
||||
Json::Value const& id = jsonRPC [jss::id];
|
||||
Json::Value const& method = jsonRPC [jss::method];
|
||||
|
||||
if (! method) {
|
||||
HTTPReply (400, "Null method", output, rpcJ);
|
||||
@@ -555,12 +567,12 @@ ServerHandlerImp::processRequest (Port const& port,
|
||||
/* ---------------------------------------------------------------------- */
|
||||
auto role = Role::FORBID;
|
||||
auto required = RPC::roleRequired(id.asString());
|
||||
if (jsonRPC.isMember("params") &&
|
||||
jsonRPC["params"].isArray() &&
|
||||
jsonRPC["params"].size() > 0 &&
|
||||
jsonRPC["params"][Json::UInt(0)].isObject())
|
||||
if (jsonRPC.isMember(jss::params) &&
|
||||
jsonRPC[jss::params].isArray() &&
|
||||
jsonRPC[jss::params].size() > 0 &&
|
||||
jsonRPC[jss::params][Json::UInt(0)].isObject())
|
||||
{
|
||||
role = requestRole(required, port, jsonRPC["params"][Json::UInt(0)],
|
||||
role = requestRole(required, port, jsonRPC[jss::params][Json::UInt(0)],
|
||||
remoteIPAddress, user);
|
||||
}
|
||||
else
|
||||
@@ -671,6 +683,12 @@ ServerHandlerImp::processRequest (Port const& port,
|
||||
|
||||
Json::Value reply (Json::objectValue);
|
||||
reply[jss::result] = std::move (result);
|
||||
if (jsonRPC.isMember(jss::jsonrpc))
|
||||
reply[jss::jsonrpc] = jsonRPC[jss::jsonrpc];
|
||||
if (jsonRPC.isMember(jss::ripplerpc))
|
||||
reply[jss::ripplerpc] = jsonRPC[jss::ripplerpc];
|
||||
if (jsonRPC.isMember(jss::id))
|
||||
reply[jss::id] = jsonRPC[jss::id];
|
||||
auto response = to_string (reply);
|
||||
|
||||
rpc_time_.notify (static_cast <beast::insight::Event::value_type> (
|
||||
|
||||
@@ -262,11 +262,6 @@ SHAMap::fetchNodeFromDB (SHAMapHash const& hash) const
|
||||
{
|
||||
auto root = std::dynamic_pointer_cast<SHAMapInnerNode>(root_);
|
||||
assert(root);
|
||||
if (!root->isEmpty())
|
||||
{
|
||||
std::cerr << "isv2 = " << isv2 << '\n';
|
||||
std::cerr << "is_v2() = " << is_v2() << '\n';
|
||||
}
|
||||
assert(root->isEmpty());
|
||||
if (isv2)
|
||||
{
|
||||
|
||||
@@ -53,6 +53,9 @@ public:
|
||||
Json::Value
|
||||
invoke(std::string const& cmd,
|
||||
Json::Value const& params = {}) = 0;
|
||||
|
||||
/// Get RPC 1.0 or RPC 2.0
|
||||
virtual unsigned version() const = 0;
|
||||
};
|
||||
|
||||
} // test
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace test {
|
||||
|
||||
/** Returns a client using JSON-RPC over HTTP/S. */
|
||||
std::unique_ptr<AbstractClient>
|
||||
makeJSONRPCClient(Config const& cfg);
|
||||
makeJSONRPCClient(Config const& cfg, unsigned rpc_version = 2);
|
||||
|
||||
} // test
|
||||
} // ripple
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
|
||||
/** Returns a client operating through WebSockets/S. */
|
||||
std::unique_ptr<WSClient>
|
||||
makeWSClient(Config const& cfg, bool v2 = true);
|
||||
makeWSClient(Config const& cfg, bool v2 = true, unsigned rpc_version = 2);
|
||||
|
||||
} // test
|
||||
} // ripple
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/test/JSONRPCClient.h>
|
||||
#include <ripple/json/json_reader.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/protocol/JsonFields.h>
|
||||
#include <ripple/server/Port.h>
|
||||
#include <beast/http/message_v1.hpp>
|
||||
#include <beast/http/streambuf_body.hpp>
|
||||
@@ -76,12 +76,14 @@ class JSONRPCClient : public AbstractClient
|
||||
boost::asio::ip::tcp::socket stream_;
|
||||
beast::streambuf bin_;
|
||||
beast::streambuf bout_;
|
||||
unsigned rpc_version_;
|
||||
|
||||
public:
|
||||
explicit
|
||||
JSONRPCClient(Config const& cfg)
|
||||
JSONRPCClient(Config const& cfg, unsigned rpc_version)
|
||||
: ep_(getEndpoint(cfg))
|
||||
, stream_(ios_)
|
||||
, rpc_version_(rpc_version)
|
||||
{
|
||||
stream_.connect(ep_);
|
||||
}
|
||||
@@ -115,10 +117,16 @@ public:
|
||||
ep_.address().to_string() + ":" + std::to_string(ep_.port()));
|
||||
{
|
||||
Json::Value jr;
|
||||
jr["method"] = cmd;
|
||||
jr[jss::method] = cmd;
|
||||
if (rpc_version_ == 2)
|
||||
{
|
||||
jr[jss::jsonrpc] = "2.0";
|
||||
jr[jss::ripplerpc] = "2.0";
|
||||
jr[jss::id] = 5;
|
||||
}
|
||||
if(params)
|
||||
{
|
||||
Json::Value& ja = jr["params"] = Json::arrayValue;
|
||||
Json::Value& ja = jr[jss::params] = Json::arrayValue;
|
||||
ja.append(params);
|
||||
}
|
||||
req.body = to_string(jr);
|
||||
@@ -138,12 +146,17 @@ public:
|
||||
jv["status"] = jv["result"]["status"];
|
||||
return jv;
|
||||
}
|
||||
|
||||
unsigned version() const override
|
||||
{
|
||||
return rpc_version_;
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<AbstractClient>
|
||||
makeJSONRPCClient(Config const& cfg)
|
||||
makeJSONRPCClient(Config const& cfg, unsigned rpc_version)
|
||||
{
|
||||
return std::make_unique<JSONRPCClient>(cfg);
|
||||
return std::make_unique<JSONRPCClient>(cfg, rpc_version);
|
||||
}
|
||||
|
||||
} // test
|
||||
|
||||
@@ -107,13 +107,16 @@ class WSClientImpl : public WSClient
|
||||
std::condition_variable cv_;
|
||||
std::list<std::shared_ptr<msg>> msgs_;
|
||||
|
||||
unsigned rpc_version_;
|
||||
|
||||
public:
|
||||
WSClientImpl(Config const& cfg, bool v2)
|
||||
WSClientImpl(Config const& cfg, bool v2, unsigned rpc_version)
|
||||
: work_(ios_)
|
||||
, strand_(ios_)
|
||||
, thread_([&]{ ios_.run(); })
|
||||
, stream_(ios_)
|
||||
, ws_(stream_)
|
||||
, rpc_version_(rpc_version)
|
||||
{
|
||||
auto const ep = getEndpoint(cfg, v2);
|
||||
stream_.connect(ep);
|
||||
@@ -143,6 +146,14 @@ public:
|
||||
Json::Value jp;
|
||||
if(params)
|
||||
jp = params;
|
||||
if (rpc_version_ == 2)
|
||||
{
|
||||
jp[jss::method] = cmd;
|
||||
jp[jss::jsonrpc] = "2.0";
|
||||
jp[jss::ripplerpc] = "2.0";
|
||||
jp[jss::id] = 5;
|
||||
}
|
||||
else
|
||||
jp[jss::command] = cmd;
|
||||
auto const s = to_string(jp);
|
||||
ws_.write_frame(true, buffer(s));
|
||||
@@ -167,7 +178,6 @@ public:
|
||||
ret[jss::status] = jss::error;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((*jv).isMember(jss::status) &&
|
||||
(*jv).isMember(jss::result))
|
||||
(*jv)[jss::result][jss::status] =
|
||||
@@ -221,6 +231,11 @@ public:
|
||||
return std::move(m->jv);
|
||||
}
|
||||
|
||||
unsigned version() const override
|
||||
{
|
||||
return rpc_version_;
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
on_read_msg(error_code const& ec)
|
||||
@@ -254,9 +269,9 @@ private:
|
||||
};
|
||||
|
||||
std::unique_ptr<WSClient>
|
||||
makeWSClient(Config const& cfg, bool v2)
|
||||
makeWSClient(Config const& cfg, bool v2, unsigned rpc_version)
|
||||
{
|
||||
return std::make_unique<WSClientImpl>(cfg, v2);
|
||||
return std::make_unique<WSClientImpl>(cfg, v2, rpc_version);
|
||||
}
|
||||
|
||||
} // test
|
||||
|
||||
@@ -537,9 +537,21 @@ Env::st (JTx const& jt)
|
||||
Json::Value
|
||||
Env::do_rpc(std::vector<std::string> const& args)
|
||||
{
|
||||
auto const jv = cmdLineToJSONRPC(args, journal);
|
||||
return client().invoke(jv["method"].asString(),
|
||||
jv["params"][0U]);
|
||||
auto jv = cmdLineToJSONRPC(args, journal);
|
||||
if (!jv.isMember(jss::jsonrpc))
|
||||
{
|
||||
jv[jss::jsonrpc] = "2.0";
|
||||
jv[jss::ripplerpc] = "2.0";
|
||||
jv[jss::id] = 5;
|
||||
}
|
||||
auto response = client().invoke(jv[jss::method].asString(), jv[jss::params][0U]);
|
||||
if (jv.isMember(jss::jsonrpc))
|
||||
{
|
||||
response[jss::jsonrpc] = jv[jss::jsonrpc];
|
||||
response[jss::ripplerpc] = jv[jss::ripplerpc];
|
||||
response[jss::id] = jv[jss::id];
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
} // jtx
|
||||
|
||||
@@ -1744,6 +1744,12 @@ public:
|
||||
auto jrr = wsc->invoke("submit", payment);
|
||||
BEAST_EXPECT(jrr[jss::status] == "success");
|
||||
BEAST_EXPECT(jrr[jss::result][jss::engine_result] == "tesSUCCESS");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jrr.isMember(jss::jsonrpc) && jrr[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jrr.isMember(jss::ripplerpc) && jrr[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jrr.isMember(jss::id) && jrr[jss::id] == 5);
|
||||
}
|
||||
|
||||
jrr = ledgerEntryState (env, alice, gw, "XTS");
|
||||
BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-101");
|
||||
|
||||
@@ -161,10 +161,141 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// Test the "signer_lists" argument in account_info, version 2 API.
|
||||
void testSignerListsV2()
|
||||
{
|
||||
using namespace jtx;
|
||||
Env env(*this, features(featureMultiSign));
|
||||
Account const alice {"alice"};
|
||||
env.fund(XRP(1000), alice);
|
||||
|
||||
auto const withoutSigners = std::string ("{ ") +
|
||||
"\"jsonrpc\": \"2.0\", "
|
||||
"\"ripplerpc\": \"2.0\", "
|
||||
"\"id\": 5, "
|
||||
"\"method\": \"account_info\", "
|
||||
"\"params\": [{ "
|
||||
"\"account\": \"" + alice.human() + "\"}]}";
|
||||
|
||||
auto const withSigners = std::string ("{ ") +
|
||||
"\"jsonrpc\": \"2.0\", "
|
||||
"\"ripplerpc\": \"2.0\", "
|
||||
"\"id\": 5, "
|
||||
"\"method\": \"account_info\", "
|
||||
"\"params\": [{ "
|
||||
"\"account\": \"" + alice.human() + "\", " +
|
||||
"\"signer_lists\": true }]}";
|
||||
// Alice has no SignerList yet.
|
||||
{
|
||||
// account_info without the "signer_lists" argument.
|
||||
auto const info = env.rpc ("json2", withoutSigners);
|
||||
BEAST_EXPECT(info.isMember(jss::result) &&
|
||||
info[jss::result].isMember(jss::account_data));
|
||||
BEAST_EXPECT(! info[jss::result][jss::account_data].
|
||||
isMember (jss::signer_lists));
|
||||
BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
|
||||
}
|
||||
{
|
||||
// account_info with the "signer_lists" argument.
|
||||
auto const info = env.rpc ("json2", withSigners);
|
||||
BEAST_EXPECT(info.isMember(jss::result) &&
|
||||
info[jss::result].isMember(jss::account_data));
|
||||
auto const& data = info[jss::result][jss::account_data];
|
||||
BEAST_EXPECT(data.isMember (jss::signer_lists));
|
||||
auto const& signerLists = data[jss::signer_lists];
|
||||
BEAST_EXPECT(signerLists.isArray());
|
||||
BEAST_EXPECT(signerLists.size() == 0);
|
||||
BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
|
||||
}
|
||||
|
||||
// Give alice a SignerList.
|
||||
Account const bogie {"bogie"};
|
||||
|
||||
Json::Value const smallSigners = signers(alice, 2, { { bogie, 3 } });
|
||||
env(smallSigners);
|
||||
{
|
||||
// account_info without the "signer_lists" argument.
|
||||
auto const info = env.rpc ("json2", withoutSigners);
|
||||
BEAST_EXPECT(info.isMember(jss::result) &&
|
||||
info[jss::result].isMember(jss::account_data));
|
||||
BEAST_EXPECT(! info[jss::result][jss::account_data].
|
||||
isMember (jss::signer_lists));
|
||||
BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
|
||||
}
|
||||
{
|
||||
// account_info with the "signer_lists" argument.
|
||||
auto const info = env.rpc ("json2", withSigners);
|
||||
BEAST_EXPECT(info.isMember(jss::result) &&
|
||||
info[jss::result].isMember(jss::account_data));
|
||||
auto const& data = info[jss::result][jss::account_data];
|
||||
BEAST_EXPECT(data.isMember (jss::signer_lists));
|
||||
auto const& signerLists = data[jss::signer_lists];
|
||||
BEAST_EXPECT(signerLists.isArray());
|
||||
BEAST_EXPECT(signerLists.size() == 1);
|
||||
auto const& signers = signerLists[0u];
|
||||
BEAST_EXPECT(signers.isObject());
|
||||
BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
|
||||
auto const& signerEntries = signers[sfSignerEntries.jsonName];
|
||||
BEAST_EXPECT(signerEntries.size() == 1);
|
||||
auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
|
||||
BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
|
||||
BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
|
||||
}
|
||||
|
||||
// Give alice a big signer list
|
||||
Account const demon {"demon"};
|
||||
Account const ghost {"ghost"};
|
||||
Account const haunt {"haunt"};
|
||||
Account const jinni {"jinni"};
|
||||
Account const phase {"phase"};
|
||||
Account const shade {"shade"};
|
||||
Account const spook {"spook"};
|
||||
|
||||
Json::Value const bigSigners = signers(alice, 4, {
|
||||
{bogie, 1}, {demon, 1}, {ghost, 1}, {haunt, 1},
|
||||
{jinni, 1}, {phase, 1}, {shade, 1}, {spook, 1}, });
|
||||
env(bigSigners);
|
||||
{
|
||||
// account_info with the "signer_lists" argument.
|
||||
auto const info = env.rpc ("json2", withSigners);
|
||||
BEAST_EXPECT(info.isMember(jss::result) &&
|
||||
info[jss::result].isMember(jss::account_data));
|
||||
auto const& data = info[jss::result][jss::account_data];
|
||||
BEAST_EXPECT(data.isMember (jss::signer_lists));
|
||||
auto const& signerLists = data[jss::signer_lists];
|
||||
BEAST_EXPECT(signerLists.isArray());
|
||||
BEAST_EXPECT(signerLists.size() == 1);
|
||||
auto const& signers = signerLists[0u];
|
||||
BEAST_EXPECT(signers.isObject());
|
||||
BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
|
||||
auto const& signerEntries = signers[sfSignerEntries.jsonName];
|
||||
BEAST_EXPECT(signerEntries.size() == 8);
|
||||
for (unsigned i = 0u; i < 8; ++i)
|
||||
{
|
||||
auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
|
||||
BEAST_EXPECT(entry.size() == 2);
|
||||
BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
|
||||
BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
|
||||
}
|
||||
BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
|
||||
}
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
testErrors();
|
||||
testSignerLists();
|
||||
testSignerListsV2();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ public:
|
||||
// which case the hash wins.
|
||||
auto const lines = env.rpc ("json", "account_lines",
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("ledger_hash": ")" + to_string(ledger4Info.hash) + R"("})"
|
||||
R"("ledger_hash": ")" + to_string(ledger4Info.hash) + R"(", )"
|
||||
R"("ledger_index": )" + std::to_string(ledger58Info.seq) + "}");
|
||||
BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
|
||||
BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
|
||||
@@ -346,10 +346,523 @@ public:
|
||||
RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]);
|
||||
}
|
||||
|
||||
// test API V2
|
||||
void testAccountLines2()
|
||||
{
|
||||
using namespace test::jtx;
|
||||
Env env(*this);
|
||||
{
|
||||
// account_lines with mal-formed json2 (missing id field).
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0")"
|
||||
" }");
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
}
|
||||
{
|
||||
// account_lines with no account.
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5)"
|
||||
" }");
|
||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
||||
RPC::missing_field_error(jss::account)[jss::error_message]);
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
|
||||
}
|
||||
{
|
||||
// account_lines with a malformed account.
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": )"
|
||||
R"("n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"}]})");
|
||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
||||
RPC::make_error(rpcBAD_SEED)[jss::error_message]);
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
|
||||
}
|
||||
Account const alice {"alice"};
|
||||
{
|
||||
// account_lines on an unfunded account.
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"("}]})");
|
||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
||||
RPC::make_error(rpcACT_NOT_FOUND)[jss::error_message]);
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
|
||||
}
|
||||
env.fund(XRP(10000), alice);
|
||||
env.close();
|
||||
LedgerInfo const ledger3Info = env.closed()->info();
|
||||
BEAST_EXPECT(ledger3Info.seq == 3);
|
||||
|
||||
{
|
||||
// alice is funded but has no lines. An empty array is returned.
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"("}]})");
|
||||
BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
|
||||
BEAST_EXPECT(lines[jss::result][jss::lines].size() == 0);
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
|
||||
}
|
||||
{
|
||||
// Specify a ledger that doesn't exist.
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("ledger_index": "nonsense"}]})");
|
||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
||||
"ledgerIndexMalformed");
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
|
||||
}
|
||||
{
|
||||
// Specify a different ledger that doesn't exist.
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("ledger_index": 50000}]})");
|
||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
||||
"ledgerNotFound");
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
|
||||
}
|
||||
// Create trust lines to share with alice.
|
||||
Account const gw1 {"gw1"};
|
||||
env.fund(XRP(10000), gw1);
|
||||
std::vector<IOU> gw1Currencies;
|
||||
|
||||
for (char c = 0; c <= ('Z' - 'A'); ++c)
|
||||
{
|
||||
// gw1 currencies have names "YAA" -> "YAZ".
|
||||
gw1Currencies.push_back(
|
||||
gw1[std::string("YA") + static_cast<char>('A' + c)]);
|
||||
IOU const& gw1Currency = gw1Currencies.back();
|
||||
|
||||
// Establish trust lines.
|
||||
env(trust(alice, gw1Currency(100 + c)));
|
||||
env(pay(gw1, alice, gw1Currency(50 + c)));
|
||||
}
|
||||
env.close();
|
||||
LedgerInfo const ledger4Info = env.closed()->info();
|
||||
BEAST_EXPECT(ledger4Info.seq == 4);
|
||||
|
||||
// Add another set of trust lines in another ledger so we can see
|
||||
// differences in historic ledgers.
|
||||
Account const gw2 {"gw2"};
|
||||
env.fund(XRP(10000), gw2);
|
||||
|
||||
// gw2 requires authorization.
|
||||
env(fset(gw2, asfRequireAuth));
|
||||
env.close();
|
||||
std::vector<IOU> gw2Currencies;
|
||||
|
||||
for (char c = 0; c <= ('Z' - 'A'); ++c)
|
||||
{
|
||||
// gw2 currencies have names "ZAA" -> "ZAZ".
|
||||
gw2Currencies.push_back(
|
||||
gw2[std::string("ZA") + static_cast<char>('A' + c)]);
|
||||
IOU const& gw2Currency = gw2Currencies.back();
|
||||
|
||||
// Establish trust lines.
|
||||
env(trust(alice, gw2Currency(200 + c)));
|
||||
env(trust(gw2, gw2Currency(0), alice, tfSetfAuth));
|
||||
env.close();
|
||||
env(pay(gw2, alice, gw2Currency(100 + c)));
|
||||
env.close();
|
||||
|
||||
// Set flags on gw2 trust lines so we can look for them.
|
||||
env(trust(alice, gw2Currency(0), gw2, tfSetNoRipple | tfSetFreeze));
|
||||
}
|
||||
env.close();
|
||||
LedgerInfo const ledger58Info = env.closed()->info();
|
||||
BEAST_EXPECT(ledger58Info.seq == 58);
|
||||
|
||||
// A re-usable test for historic ledgers.
|
||||
auto testAccountLinesHistory =
|
||||
[this, &env](Account const& account, LedgerInfo const& info, int count)
|
||||
{
|
||||
// Get account_lines by ledger index.
|
||||
auto const linesSeq = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + account.human() + R"(", )"
|
||||
R"("ledger_index": )" + std::to_string(info.seq) + "}]}");
|
||||
BEAST_EXPECT(linesSeq[jss::result][jss::lines].isArray());
|
||||
BEAST_EXPECT(linesSeq[jss::result][jss::lines].size() == count);
|
||||
BEAST_EXPECT(linesSeq.isMember(jss::jsonrpc) && linesSeq[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(linesSeq.isMember(jss::ripplerpc) && linesSeq[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(linesSeq.isMember(jss::id) && linesSeq[jss::id] == 5);
|
||||
|
||||
// Get account_lines by ledger hash.
|
||||
auto const linesHash = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + account.human() + R"(", )"
|
||||
R"("ledger_hash": ")" + to_string(info.hash) + R"("}]})");
|
||||
BEAST_EXPECT(linesHash[jss::result][jss::lines].isArray());
|
||||
BEAST_EXPECT(linesHash[jss::result][jss::lines].size() == count);
|
||||
BEAST_EXPECT(linesHash.isMember(jss::jsonrpc) && linesHash[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(linesHash.isMember(jss::ripplerpc) && linesHash[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(linesHash.isMember(jss::id) && linesHash[jss::id] == 5);
|
||||
};
|
||||
|
||||
// Alice should have no trust lines in ledger 3.
|
||||
testAccountLinesHistory (alice, ledger3Info, 0);
|
||||
|
||||
// Alice should have 26 trust lines in ledger 4.
|
||||
testAccountLinesHistory (alice, ledger4Info, 26);
|
||||
|
||||
// Alice should have 52 trust lines in ledger 58.
|
||||
testAccountLinesHistory (alice, ledger58Info, 52);
|
||||
|
||||
{
|
||||
// Surprisingly, it's valid to specify both index and hash, in
|
||||
// which case the hash wins.
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("ledger_hash": ")" + to_string(ledger4Info.hash) + R"(", )"
|
||||
R"("ledger_index": )" + std::to_string(ledger58Info.seq) + "}]}");
|
||||
BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
|
||||
BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
|
||||
}
|
||||
{
|
||||
// alice should have 52 trust lines in the current ledger.
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"("}]})");
|
||||
BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
|
||||
BEAST_EXPECT(lines[jss::result][jss::lines].size() == 52);
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
|
||||
}
|
||||
{
|
||||
// alice should have 26 trust lines with gw1.
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("peer": ")" + gw1.human() + R"("}]})");
|
||||
BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
|
||||
BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
|
||||
}
|
||||
{
|
||||
// Use a malformed peer.
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("peer": )"
|
||||
R"("n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"}]})");
|
||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
||||
RPC::make_error(rpcBAD_SEED)[jss::error_message]);
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
|
||||
}
|
||||
{
|
||||
// A negative limit should fail.
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("limit": -1}]})");
|
||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
||||
RPC::expected_field_message(jss::limit, "unsigned integer"));
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
|
||||
}
|
||||
{
|
||||
// Limit the response to 1 trust line.
|
||||
auto const linesA = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("limit": 1}]})");
|
||||
BEAST_EXPECT(linesA[jss::result][jss::lines].isArray());
|
||||
BEAST_EXPECT(linesA[jss::result][jss::lines].size() == 1);
|
||||
BEAST_EXPECT(linesA.isMember(jss::jsonrpc) && linesA[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(linesA.isMember(jss::ripplerpc) && linesA[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(linesA.isMember(jss::id) && linesA[jss::id] == 5);
|
||||
|
||||
// Pick up from where the marker left off. We should get 51.
|
||||
auto marker = linesA[jss::result][jss::marker].asString();
|
||||
auto const linesB = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("marker": ")" + marker + R"("}]})");
|
||||
BEAST_EXPECT(linesB[jss::result][jss::lines].isArray());
|
||||
BEAST_EXPECT(linesB[jss::result][jss::lines].size() == 51);
|
||||
BEAST_EXPECT(linesB.isMember(jss::jsonrpc) && linesB[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(linesB.isMember(jss::ripplerpc) && linesB[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(linesB.isMember(jss::id) && linesB[jss::id] == 5);
|
||||
|
||||
// Go again from where the marker left off, but set a limit of 3.
|
||||
auto const linesC = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("limit": 3, )"
|
||||
R"("marker": ")" + marker + R"("}]})");
|
||||
BEAST_EXPECT(linesC[jss::result][jss::lines].isArray());
|
||||
BEAST_EXPECT(linesC[jss::result][jss::lines].size() == 3);
|
||||
BEAST_EXPECT(linesC.isMember(jss::jsonrpc) && linesC[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(linesC.isMember(jss::ripplerpc) && linesC[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(linesC.isMember(jss::id) && linesC[jss::id] == 5);
|
||||
|
||||
// Mess with the marker so it becomes bad and check for the error.
|
||||
marker[5] = marker[5] == '7' ? '8' : '7';
|
||||
auto const linesD = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("marker": ")" + marker + R"("}]})");
|
||||
BEAST_EXPECT(linesD[jss::result][jss::error_message] ==
|
||||
RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]);
|
||||
BEAST_EXPECT(linesD.isMember(jss::jsonrpc) && linesD[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(linesD.isMember(jss::ripplerpc) && linesD[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(linesD.isMember(jss::id) && linesD[jss::id] == 5);
|
||||
}
|
||||
{
|
||||
// A non-string marker should also fail.
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("marker": true}]})");
|
||||
BEAST_EXPECT(lines[jss::result][jss::error_message] ==
|
||||
RPC::expected_field_message(jss::marker, "string"));
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
|
||||
}
|
||||
{
|
||||
// Check that the flags we expect from alice to gw2 are present.
|
||||
auto const lines = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("limit": 1, )"
|
||||
R"("peer": ")" + gw2.human() + R"("}]})");
|
||||
auto const& line = lines[jss::result][jss::lines][0u];
|
||||
BEAST_EXPECT(line[jss::freeze].asBool() == true);
|
||||
BEAST_EXPECT(line[jss::no_ripple].asBool() == true);
|
||||
BEAST_EXPECT(line[jss::peer_authorized].asBool() == true);
|
||||
BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
|
||||
}
|
||||
{
|
||||
// Check that the flags we expect from gw2 to alice are present.
|
||||
auto const linesA = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + gw2.human() + R"(", )"
|
||||
R"("limit": 1, )"
|
||||
R"("peer": ")" + alice.human() + R"("}]})");
|
||||
auto const& lineA = linesA[jss::result][jss::lines][0u];
|
||||
BEAST_EXPECT(lineA[jss::freeze_peer].asBool() == true);
|
||||
BEAST_EXPECT(lineA[jss::no_ripple_peer].asBool() == true);
|
||||
BEAST_EXPECT(lineA[jss::authorized].asBool() == true);
|
||||
BEAST_EXPECT(linesA.isMember(jss::jsonrpc) && linesA[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(linesA.isMember(jss::ripplerpc) && linesA[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(linesA.isMember(jss::id) && linesA[jss::id] == 5);
|
||||
|
||||
// Continue from the returned marker to make sure that works.
|
||||
BEAST_EXPECT(linesA[jss::result].isMember(jss::marker));
|
||||
auto const marker = linesA[jss::result][jss::marker].asString();
|
||||
auto const linesB = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + gw2.human() + R"(", )"
|
||||
R"("limit": 25, )"
|
||||
R"("marker": ")" + marker + R"(", )"
|
||||
R"("peer": ")" + alice.human() + R"("}]})");
|
||||
BEAST_EXPECT(linesB[jss::result][jss::lines].isArray());
|
||||
BEAST_EXPECT(linesB[jss::result][jss::lines].size() == 25);
|
||||
BEAST_EXPECT(! linesB[jss::result].isMember(jss::marker));
|
||||
BEAST_EXPECT(linesB.isMember(jss::jsonrpc) && linesB[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(linesB.isMember(jss::ripplerpc) && linesB[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(linesB.isMember(jss::id) && linesB[jss::id] == 5);
|
||||
}
|
||||
}
|
||||
|
||||
// test API V2
|
||||
void testAccountLineDelete2()
|
||||
{
|
||||
using namespace test::jtx;
|
||||
Env env(*this);
|
||||
|
||||
// The goal here is to observe account_lines marker behavior if the
|
||||
// entry pointed at by a returned marker is removed from the ledger.
|
||||
//
|
||||
// It isn't easy to explicitly delete a trust line, so we do so in a
|
||||
// round-about fashion. It takes 4 actors:
|
||||
// o Gateway gw1 issues USD
|
||||
// o alice offers to buy 100 USD for 100 XRP.
|
||||
// o becky offers to sell 100 USD for 100 XRP.
|
||||
// There will now be an inferred trustline between alice and gw1.
|
||||
// o alice pays her 100 USD to cheri.
|
||||
// alice should now have no USD and no trustline to gw1.
|
||||
Account const alice {"alice"};
|
||||
Account const becky {"becky"};
|
||||
Account const cheri {"cheri"};
|
||||
Account const gw1 {"gw1"};
|
||||
Account const gw2 {"gw2"};
|
||||
env.fund(XRP(10000), alice, becky, cheri, gw1, gw2);
|
||||
env.close();
|
||||
|
||||
auto const USD = gw1["USD"];
|
||||
auto const EUR = gw2["EUR"];
|
||||
env(trust(alice, EUR(200)));
|
||||
env(trust(becky, USD(200)));
|
||||
env(trust(cheri, USD(200)));
|
||||
env.close();
|
||||
|
||||
// becky gets 100 USD from gw1.
|
||||
env(pay(gw1, becky, USD(100)));
|
||||
env.close();
|
||||
|
||||
// alice offers to buy 100 USD for 100 XRP.
|
||||
env(offer(alice, USD(100), XRP(100)));
|
||||
env.close();
|
||||
|
||||
// becky offers to buy 100 XRP for 100 USD.
|
||||
env(offer(becky, XRP(100), USD(100)));
|
||||
env.close();
|
||||
|
||||
// Get account_lines for alice. Limit at 1, so we get a marker.
|
||||
auto const linesBeg = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("limit": 1}]})");
|
||||
BEAST_EXPECT(linesBeg[jss::result][jss::lines][0u][jss::currency] == "EUR");
|
||||
BEAST_EXPECT(linesBeg[jss::result].isMember(jss::marker));
|
||||
BEAST_EXPECT(linesBeg.isMember(jss::jsonrpc) && linesBeg[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(linesBeg.isMember(jss::ripplerpc) && linesBeg[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(linesBeg.isMember(jss::id) && linesBeg[jss::id] == 5);
|
||||
|
||||
// alice pays 100 USD to cheri.
|
||||
env(pay(alice, cheri, USD(100)));
|
||||
env.close();
|
||||
|
||||
// Since alice paid all her USD to cheri, alice should no longer
|
||||
// have a trust line to gw1. So the old marker should now be invalid.
|
||||
auto const linesEnd = env.rpc ("json2", "{ "
|
||||
R"("method" : "account_lines",)"
|
||||
R"("jsonrpc" : "2.0",)"
|
||||
R"("ripplerpc" : "2.0",)"
|
||||
R"("id" : 5,)"
|
||||
R"("params": [ )"
|
||||
R"({"account": ")" + alice.human() + R"(", )"
|
||||
R"("marker": ")" +
|
||||
linesBeg[jss::result][jss::marker].asString() + R"("}]})");
|
||||
BEAST_EXPECT(linesEnd[jss::result][jss::error_message] ==
|
||||
RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]);
|
||||
BEAST_EXPECT(linesEnd.isMember(jss::jsonrpc) && linesEnd[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(linesEnd.isMember(jss::ripplerpc) && linesEnd[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(linesEnd.isMember(jss::id) && linesEnd[jss::id] == 5);
|
||||
}
|
||||
|
||||
void run ()
|
||||
{
|
||||
testAccountLines();
|
||||
testAccountLineDelete();
|
||||
testAccountLines2();
|
||||
testAccountLineDelete2();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -72,6 +72,12 @@ public:
|
||||
}
|
||||
|
||||
auto jv = wsc->invoke("subscribe", books);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
if(! BEAST_EXPECT(jv[jss::status] == "success"))
|
||||
return;
|
||||
BEAST_EXPECT(jv[jss::result].isMember(jss::offers) &&
|
||||
@@ -106,8 +112,14 @@ public:
|
||||
}
|
||||
|
||||
// RPC unsubscribe
|
||||
BEAST_EXPECT(wsc->invoke("unsubscribe",
|
||||
books)[jss::status] == "success");
|
||||
auto jv = wsc->invoke("unsubscribe", books);
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -143,6 +155,12 @@ public:
|
||||
}
|
||||
|
||||
auto jv = wsc->invoke("subscribe", books);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
if(! BEAST_EXPECT(jv[jss::status] == "success"))
|
||||
return;
|
||||
BEAST_EXPECT(jv[jss::result].isMember(jss::offers) &&
|
||||
@@ -181,8 +199,14 @@ public:
|
||||
}
|
||||
|
||||
// RPC unsubscribe
|
||||
BEAST_EXPECT(wsc->invoke("unsubscribe",
|
||||
books)[jss::status] == "success");
|
||||
auto jv = wsc->invoke("unsubscribe", books);
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -210,6 +234,12 @@ public:
|
||||
}
|
||||
|
||||
auto jv = wsc->invoke("subscribe", books);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
if(! BEAST_EXPECT(jv[jss::status] == "success"))
|
||||
return;
|
||||
BEAST_EXPECT(jv[jss::result].isMember(jss::asks) &&
|
||||
@@ -254,8 +284,14 @@ public:
|
||||
}
|
||||
|
||||
// RPC unsubscribe
|
||||
BEAST_EXPECT(wsc->invoke("unsubscribe",
|
||||
books)[jss::status] == "success");
|
||||
auto jv = wsc->invoke("unsubscribe", books);
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -292,6 +328,12 @@ public:
|
||||
}
|
||||
|
||||
auto jv = wsc->invoke("subscribe", books);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
if(! BEAST_EXPECT(jv[jss::status] == "success"))
|
||||
return;
|
||||
BEAST_EXPECT(jv[jss::result].isMember(jss::asks) &&
|
||||
@@ -344,8 +386,14 @@ public:
|
||||
}
|
||||
|
||||
// RPC unsubscribe
|
||||
BEAST_EXPECT(wsc->invoke("unsubscribe",
|
||||
books)[jss::status] == "success");
|
||||
auto jv = wsc->invoke("unsubscribe", books);
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -382,6 +430,12 @@ public:
|
||||
}
|
||||
|
||||
auto jv = wsc->invoke("subscribe", books);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
if(! BEAST_EXPECT(jv[jss::status] == "success"))
|
||||
return;
|
||||
BEAST_EXPECT(jv[jss::result].isMember(jss::offers) &&
|
||||
@@ -441,8 +495,14 @@ public:
|
||||
}
|
||||
|
||||
// RPC unsubscribe
|
||||
BEAST_EXPECT(wsc->invoke("unsubscribe",
|
||||
books)[jss::status] == "success");
|
||||
auto jv = wsc->invoke("unsubscribe", books);
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -496,6 +556,12 @@ public:
|
||||
}
|
||||
|
||||
auto jv = wsc->invoke("subscribe", books);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
if(! BEAST_EXPECT(jv[jss::status] == "success"))
|
||||
return;
|
||||
BEAST_EXPECT(jv[jss::result].isMember(jss::offers) &&
|
||||
@@ -563,8 +629,14 @@ public:
|
||||
}
|
||||
|
||||
// RPC unsubscribe
|
||||
BEAST_EXPECT(wsc->invoke("unsubscribe",
|
||||
books)[jss::status] == "success");
|
||||
auto jv = wsc->invoke("unsubscribe", books);
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -603,6 +675,12 @@ public:
|
||||
}
|
||||
|
||||
auto jv = wsc->invoke("subscribe", books);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
if(! BEAST_EXPECT(jv[jss::status] == "success"))
|
||||
return;
|
||||
BEAST_EXPECT(jv[jss::result].isMember(jss::asks) &&
|
||||
@@ -681,8 +759,14 @@ public:
|
||||
}
|
||||
|
||||
// RPC unsubscribe
|
||||
BEAST_EXPECT(wsc->invoke("unsubscribe",
|
||||
books)[jss::status] == "success");
|
||||
auto jv = wsc->invoke("unsubscribe", books);
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -739,6 +823,12 @@ public:
|
||||
}
|
||||
|
||||
auto jv = wsc->invoke("subscribe", books);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
if(! BEAST_EXPECT(jv[jss::status] == "success"))
|
||||
return;
|
||||
BEAST_EXPECT(jv[jss::result].isMember(jss::asks) &&
|
||||
@@ -833,8 +923,14 @@ public:
|
||||
}
|
||||
|
||||
// RPC unsubscribe
|
||||
BEAST_EXPECT(wsc->invoke("unsubscribe",
|
||||
books)[jss::status] == "success");
|
||||
auto jv = wsc->invoke("unsubscribe", books);
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -863,6 +959,12 @@ public:
|
||||
}
|
||||
|
||||
auto jv = wsc->invoke("subscribe", books);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
if(! BEAST_EXPECT(jv[jss::status] == "success"))
|
||||
return;
|
||||
BEAST_EXPECT(jv[jss::result].isMember(jss::offers) &&
|
||||
@@ -886,7 +988,15 @@ public:
|
||||
jvParams[jss::ledger_index] = "validated";
|
||||
jvParams[jss::taker_gets][jss::currency] = "USD";
|
||||
jvParams[jss::taker_gets][jss::issuer] = gw.human();
|
||||
auto jrr = wsc->invoke("book_offers", jvParams)[jss::result];
|
||||
|
||||
auto jv = wsc->invoke("book_offers", jvParams);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
auto jrr = jv[jss::result];
|
||||
|
||||
BEAST_EXPECT(jrr[jss::offers].isArray());
|
||||
BEAST_EXPECT(jrr[jss::offers].size() == 1);
|
||||
@@ -927,7 +1037,14 @@ public:
|
||||
t[jss::TakerPays] == XRP(2000).value().getJson(0);
|
||||
}));
|
||||
|
||||
jrr = wsc->invoke("book_offers", jvParams)[jss::result];
|
||||
jv = wsc->invoke("book_offers", jvParams);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
jrr = jv[jss::result];
|
||||
|
||||
BEAST_EXPECT(jrr[jss::offers].isArray());
|
||||
BEAST_EXPECT(jrr[jss::offers].size() == 2);
|
||||
@@ -946,8 +1063,14 @@ public:
|
||||
BEAST_EXPECT(jrNextOffer[jss::owner_funds] == "50");
|
||||
BEAST_EXPECT(jrNextOffer[jss::quality] == "400000000");
|
||||
|
||||
BEAST_EXPECT(wsc->invoke("unsubscribe",
|
||||
books)[jss::status] == "success");
|
||||
jv = wsc->invoke("unsubscribe", books);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -86,6 +86,12 @@ public:
|
||||
|
||||
auto jv = wsc->invoke("gateway_balances", qry);
|
||||
expect(jv[jss::status] == "success");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
expect(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
expect(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
expect(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
|
||||
auto const& result = jv[jss::result];
|
||||
expect(result[jss::account] == alice.human());
|
||||
|
||||
@@ -45,6 +45,12 @@ public:
|
||||
jv[jss::streams].append("transactions");
|
||||
jv = wsc->invoke("subscribe", jv);
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -54,6 +60,12 @@ public:
|
||||
payment[jss::tx_json] = pay("alice", "bob", XRP(1));
|
||||
payment[jss::tx_json][sfLastLedgerSequence.fieldName] = 1;
|
||||
auto jv = wsc->invoke("submit", payment);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::result][jss::engine_result] ==
|
||||
"tefMAX_LEDGER");
|
||||
|
||||
@@ -62,6 +74,12 @@ public:
|
||||
payment[jss::tx_json][sfSequence.fieldName] =
|
||||
env.seq("alice") - 1;
|
||||
jv = wsc->invoke("submit", payment);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::result][jss::engine_result] ==
|
||||
"tefPAST_SEQ");
|
||||
|
||||
@@ -69,6 +87,12 @@ public:
|
||||
payment[jss::tx_json][sfSequence.fieldName] =
|
||||
env.seq("alice") + 1;
|
||||
jv = wsc->invoke("submit", payment);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::result][jss::engine_result] ==
|
||||
"terPRE_SEQ");
|
||||
|
||||
@@ -76,6 +100,12 @@ public:
|
||||
payment[jss::tx_json][sfSequence.fieldName] =
|
||||
env.seq("alice");
|
||||
jv = wsc->invoke("submit", payment);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::result][jss::engine_result] ==
|
||||
"tesSUCCESS");
|
||||
|
||||
@@ -84,6 +114,12 @@ public:
|
||||
|
||||
// Finalize transactions
|
||||
jv = wsc->invoke("ledger_accept");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::result].isMember(
|
||||
jss::ledger_current_index));
|
||||
}
|
||||
@@ -115,6 +151,12 @@ public:
|
||||
jv[jss::streams] = Json::arrayValue;
|
||||
jv[jss::streams].append("transactions");
|
||||
jv = wsc->invoke("unsubscribe", jv);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
}
|
||||
@@ -145,6 +187,12 @@ public:
|
||||
jv[jss::secret] = toBase58(generateSeed("alice"));
|
||||
jv[jss::tx_json] = pay("alice", "bob", XRP(1));
|
||||
jv = wsc->invoke("submit", jv);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::result][jss::engine_result] ==
|
||||
"tesSUCCESS");
|
||||
|
||||
@@ -163,6 +211,12 @@ public:
|
||||
jv[jss::ledger_index_max] = -1;
|
||||
wsc = makeWSClient(env.app().config());
|
||||
jv = wsc->invoke("account_tx", jv);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
|
||||
// Check balance
|
||||
auto ff = jv[jss::result][jss::transactions][0u][jss::meta]
|
||||
@@ -189,11 +243,23 @@ public:
|
||||
jv[jss::secret] = toBase58(generateSeed("alice"));
|
||||
jv[jss::tx_json] = pay("alice", "bob", XRP(1));
|
||||
jv = wsc->invoke("submit", jv);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::result][jss::engine_result] ==
|
||||
"tesSUCCESS");
|
||||
|
||||
// Finalize transaction
|
||||
jv = wsc->invoke("ledger_accept");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::result].isMember(
|
||||
jss::ledger_current_index));
|
||||
|
||||
@@ -208,13 +274,26 @@ public:
|
||||
jv[jss::streams] = Json::arrayValue;
|
||||
jv[jss::streams].append("ledger");
|
||||
jv = wsc->invoke("subscribe", jv);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
// Close ledgers
|
||||
for(auto i = 0; i < 8; ++i)
|
||||
{
|
||||
BEAST_EXPECT(wsc->invoke("ledger_accept")[jss::result].
|
||||
auto jv = wsc->invoke("ledger_accept");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::result].
|
||||
isMember(jss::ledger_current_index));
|
||||
|
||||
// Wait for the jobqueue to process everything
|
||||
@@ -233,6 +312,12 @@ public:
|
||||
jv[jss::streams] = Json::arrayValue;
|
||||
jv[jss::streams].append("ledger");
|
||||
jv = wsc->invoke("unsubscribe", jv);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
}
|
||||
@@ -246,13 +331,26 @@ public:
|
||||
jv[jss::streams] = Json::arrayValue;
|
||||
jv[jss::streams].append("ledger");
|
||||
jv = wsc->invoke("subscribe", jv);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
// Close ledgers
|
||||
for (auto i = 0; i < 2; ++i)
|
||||
{
|
||||
BEAST_EXPECT(wsc->invoke("ledger_accept")[jss::result].
|
||||
auto jv = wsc->invoke("ledger_accept");
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::result].
|
||||
isMember(jss::ledger_current_index));
|
||||
|
||||
// Wait for the jobqueue to process everything
|
||||
@@ -271,6 +369,12 @@ public:
|
||||
jv[jss::streams] = Json::arrayValue;
|
||||
jv[jss::streams].append("ledger");
|
||||
jv = wsc->invoke("unsubscribe", jv);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
}
|
||||
@@ -283,6 +387,12 @@ public:
|
||||
jv[jss::ledger_index_max] = -1;
|
||||
wsc = makeWSClient(env.app().config());
|
||||
jv = wsc->invoke("account_tx", jv);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
|
||||
// Check balance
|
||||
auto ff = jv[jss::result][jss::transactions][0u][jss::meta]
|
||||
@@ -310,6 +420,12 @@ public:
|
||||
jv[jss::accounts_proposed].append(
|
||||
Account("alice").human());
|
||||
jv = wsc->invoke("subscribe", jv);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
@@ -320,6 +436,12 @@ public:
|
||||
jv[jss::tx_json] = fset("alice", 0);
|
||||
jv[jss::tx_json][jss::Fee] = 10;
|
||||
jv = wsc->invoke("submit", jv);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::result][jss::engine_result] ==
|
||||
"tesSUCCESS");
|
||||
}
|
||||
@@ -341,6 +463,12 @@ public:
|
||||
jv[jss::accounts_proposed].append(
|
||||
Account("alice").human());
|
||||
jv = wsc->invoke("unsubscribe", jv);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,12 @@ public:
|
||||
stream[jss::streams] = Json::arrayValue;
|
||||
stream[jss::streams].append("server");
|
||||
auto jv = wsc->invoke("subscribe", stream);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
@@ -63,6 +69,12 @@ public:
|
||||
{
|
||||
// RPC unsubscribe
|
||||
auto jv = wsc->invoke("unsubscribe", stream);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
@@ -91,6 +103,12 @@ public:
|
||||
stream[jss::streams] = Json::arrayValue;
|
||||
stream[jss::streams].append("ledger");
|
||||
auto jv = wsc->invoke("subscribe", stream);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::result][jss::ledger_index] == 2);
|
||||
}
|
||||
|
||||
@@ -120,6 +138,12 @@ public:
|
||||
|
||||
// RPC unsubscribe
|
||||
auto jv = wsc->invoke("unsubscribe", stream);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
@@ -136,6 +160,12 @@ public:
|
||||
stream[jss::streams] = Json::arrayValue;
|
||||
stream[jss::streams].append("transactions");
|
||||
auto jv = wsc->invoke("subscribe", stream);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
@@ -186,6 +216,12 @@ public:
|
||||
{
|
||||
// RPC unsubscribe
|
||||
auto jv = wsc->invoke("unsubscribe", stream);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
@@ -195,6 +231,12 @@ public:
|
||||
stream[jss::accounts] = Json::arrayValue;
|
||||
stream[jss::accounts].append(Account("alice").human());
|
||||
auto jv = wsc->invoke("subscribe", stream);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
@@ -228,6 +270,12 @@ public:
|
||||
|
||||
// RPC unsubscribe
|
||||
auto jv = wsc->invoke("unsubscribe", stream);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
@@ -243,11 +291,23 @@ public:
|
||||
stream[jss::streams] = Json::arrayValue;
|
||||
stream[jss::streams].append("manifests");
|
||||
auto jv = wsc->invoke("subscribe", stream);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
// RPC unsubscribe
|
||||
auto jv = wsc->invoke("unsubscribe", stream);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
@@ -295,6 +355,12 @@ public:
|
||||
stream[jss::streams] = Json::arrayValue;
|
||||
stream[jss::streams].append("validations");
|
||||
auto jv = wsc->invoke("subscribe", stream);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
@@ -323,6 +389,12 @@ public:
|
||||
|
||||
// RPC unsubscribe
|
||||
auto jv = wsc->invoke("unsubscribe", stream);
|
||||
if (wsc->version() == 2)
|
||||
{
|
||||
BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
|
||||
BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
|
||||
}
|
||||
BEAST_EXPECT(jv[jss::status] == "success");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user