A multithreaded websocket client library for interacting with the xrp ledger's json rpc. At its core, the client maintains a single websocket connection, but is able to make atomic requests to the json rpc with a single function call, or make subscriptions with a function that returns a listener for incoming messages. These features are implemented using the websocket implementation by tokio-tungstenite
, as well as using channels implemented by tokio::sync
.
This client library was written to be as close to the javascript client as possible. A common example with the javascript library would be as follows:
```js import { Client } from "xrpl";
async function main() { const client = new Client("wss://xrpl.ws"); const res = await client.request({ command: "account_info", account: "r...", }); console.log(res); } ```
Using this client, the same request may be performed as:
```rust use xrpl::{XrplClient, request};
async fn main() { let account = "r..."; // an xrpl address let client = XrplClient::new("wss://xrpl.ws").await.unwrap(); let serverinfo = client.request(request::AccountInfo { account: "r...".into(), ..Default::default() }).await; println!("{serverinfo}"); } ```
Subscriptions, on the other hand, are handled somewhat differently. In javascript, a subscription would look look something like:
```js import { Client } from "xrpl";
async function main() { const client = new Client("wss://xrpl.ws"); const subscriptionres = await client.request({ command: "subscribe", streams: ["ledger"], }); console.log(subscriptionres); // an acknowledgement message wiht some relevant data client.on("ledgerClosed", (msg) => console.log(msg)); // the actual messages, delivered via a callback } ```
In this library, the same subscription would look something like this
rust
async fn main() {
let client = XrplClient::new("wss://xrpl.ws").await.unwrap();
let (subscription_res, receiver) = client.request(subscription::LedgerClosed).await;
println!("{subscription_res:?}"); // the acknowledgement message with data etc...
loop {
let msg = receiver.recv().await;
match msg {
Ok(msg) => println!("{msg:#?}"), // the actual messages
Err(e) => {
eprintln!("{e:#?}");
break;
}
}
}
}
The receiver is implemented using mpsc::broadcast, and as such can be quite trivially cloned through receiver.resubscribe()
, or even moved into a different thread etc.