xrpl_rs/lib.rs
1//! A client that exposes methods for interacting with the XRP Ledger.
2//!
3//! # Example Usage
4//! ```
5//! use std::convert::TryInto;
6//! use xrpl_rs::{XRPL, transports::HTTP, types::account::AccountInfoRequest, types::CurrencyAmount};
7//! use tokio_test::block_on;
8//!
9//! // Create a new XRPL client with the HTTP transport.
10//! let xrpl = XRPL::new(
11//! HTTP::builder()
12//! .with_endpoint("http://s1.ripple.com:51234/")
13//! .unwrap()
14//! .build()
15//! .unwrap());
16//!
17//! // Create a request
18//! let mut req = AccountInfoRequest::default();
19//! req.account = "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn".to_owned();
20//!
21//! // Fetch the account info for an address.
22//! let account_info = block_on(async {
23//! xrpl
24//! .account_info(req)
25//! .await
26//! .unwrap()
27//! });
28//!
29//! assert_eq!(account_info.account_data.balance, CurrencyAmount::xrp(9977));
30//! ```
31
32use std::pin::Pin;
33
34use futures::stream::Stream;
35use serde::de::DeserializeOwned;
36use transports::{DuplexTransport, Transport, TransportError};
37use types::{
38 account::{
39 AccountChannelsRequest, AccountChannelsResponse, AccountCurrenciesRequest,
40 AccountCurrenciesResponse, AccountInfoRequest, AccountInfoResponse, AccountLinesRequest,
41 AccountLinesResponse, AccountOfferRequest, AccountOfferResponse,
42 },
43 channels::{ChannelVerifyRequest, ChannelVerifyResponse},
44 fee::{FeeRequest, FeeResponse},
45 ledger::{LedgerRequest, LedgerResponse},
46 submit::{SignAndSubmitRequest, SubmitRequest, SubmitResponse},
47 subscribe::{SubscribeRequest, SubscriptionEvent},
48 tx::{TxRequest, TxResponse},
49 TransactionEntryRequest, TransactionEntryResponse,
50};
51
52pub mod transaction;
53pub mod transports;
54pub mod types;
55pub mod utils;
56pub mod wallet;
57
58/// An enum providing error types that can be returned when calling XRPL methods.
59#[derive(Debug)]
60pub enum Error {
61 TransportError(TransportError),
62}
63
64impl From<TransportError> for Error {
65 fn from(e: TransportError) -> Self {
66 Self::TransportError(e)
67 }
68}
69
70/// A client that exposes methods for interacting with the XRP Ledger.
71///
72/// # Examples
73/// ```
74/// use std::convert::TryInto;
75/// use xrpl_rs::{XRPL, transports::HTTP, types::account::AccountInfoRequest, types::CurrencyAmount};
76/// use tokio_test::block_on;
77///
78/// // Create a new XRPL client with the HTTP transport.
79/// let xrpl = XRPL::new(
80/// HTTP::builder()
81/// .with_endpoint("http://s1.ripple.com:51234/")
82/// .unwrap()
83/// .build()
84/// .unwrap());
85///
86/// // Create a request
87/// let mut req = AccountInfoRequest::default();
88/// req.account = "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn".to_owned();
89///
90/// // Fetch the account info for an address.
91/// let account_info = block_on(async {
92/// xrpl
93/// .account_info(req)
94/// .await
95/// .unwrap()
96/// });
97///
98/// assert_eq!(account_info.account_data.balance, CurrencyAmount::xrp(9977));
99/// ```
100pub struct XRPL<T: Transport> {
101 transport: T,
102}
103
104macro_rules! impl_rpc_method {
105 ($(#[$attr:meta])* $name: ident, $method: expr, $request: ident, $response: ident) => {
106 $(#[$attr])*
107 pub async fn $name(&self, params: $request) -> Result<$response, Error> {
108 Ok(self
109 .transport
110 .send_request::<$request, $response>($method, params)
111 .await?)
112 }
113 };
114}
115
116impl<T: Transport> XRPL<T> {
117 pub fn new(transport: T) -> Self {
118 Self { transport }
119 }
120 impl_rpc_method!(
121 /// The account_channels method returns information about an account's Payment Channels. This includes only channels where the specified account is the channel's source, not the destination. (A channel's "source" and "owner" are the same.) All information retrieved is relative to a particular version of the ledger.
122 account_channels,
123 "account_channels",
124 AccountChannelsRequest,
125 AccountChannelsResponse
126 );
127 impl_rpc_method!(
128 /// The account_currencies command retrieves a list of currencies that an account can send or receive, based on its trust lines. (This is not a thoroughly confirmed list, but it can be used to populate user interfaces.)
129 account_currencies,
130 "account_currencies",
131 AccountCurrenciesRequest,
132 AccountCurrenciesResponse
133 );
134 impl_rpc_method!(
135 /// The account_info command retrieves information about an account, its activity, and its XRP balance. All information retrieved is relative to a particular version of the ledger.
136 account_info,
137 "account_info",
138 AccountInfoRequest,
139 AccountInfoResponse
140 );
141 impl_rpc_method!(
142 /// The account_lines method returns information about an account's trust lines, including balances in all non-XRP currencies and assets. All information retrieved is relative to a particular version of the ledger.
143 account_lines,
144 "account_lines",
145 AccountLinesRequest,
146 AccountLinesResponse
147 );
148 impl_rpc_method!(
149 /// The account_offers method retrieves a list of offers made by a given account that are outstanding as of a particular ledger version.
150 account_offers,
151 "account_offers",
152 AccountOfferRequest,
153 AccountOfferResponse
154 );
155 impl_rpc_method!(
156 /// The transaction_entry method retrieves information on a single transaction from a specific ledger version. (The tx method, by contrast, searches all ledgers for the specified transaction. We recommend using that method instead.)
157 transaction_entry,
158 "transaction_entry",
159 TransactionEntryRequest,
160 TransactionEntryResponse
161 );
162 impl_rpc_method!(
163 /// The submit method applies a transaction and sends it to the network to be confirmed and included in future ledgers.
164 submit,
165 "submit",
166 SubmitRequest,
167 SubmitResponse
168 );
169 impl_rpc_method!(
170 /// The sign_and_submit method applies a transaction and sends it to the network to be confirmed and included in future ledgers.
171 sign_and_submit,
172 "submit",
173 SignAndSubmitRequest,
174 SubmitResponse
175 );
176 impl_rpc_method!(
177 /// The fee command reports the current state of the open-ledger requirements for the transaction cost. This requires the FeeEscalation amendment to be enabled. New in: rippled 0.31.0.
178 fee,
179 "fee",
180 FeeRequest,
181 FeeResponse
182 );
183 impl_rpc_method!(
184 /// Retrieve information about the public ledger.
185 ledger,
186 "ledger",
187 LedgerRequest,
188 LedgerResponse
189 );
190 impl_rpc_method!(
191 /// The channel_verify method checks the validity of a signature that can be used to redeem a specific amount of XRP from a payment channel.
192 channel_verify,
193 "channel_verify",
194 ChannelVerifyRequest,
195 ChannelVerifyResponse
196 );
197 impl_rpc_method!(
198 /// The tx method retrieves information on a single transaction, by its identifying hash.
199 tx,
200 "tx",
201 TxRequest,
202 TxResponse
203 );
204}
205
206impl<T: DuplexTransport> XRPL<T> {
207 pub async fn subscribe(
208 &self,
209 request: SubscribeRequest,
210 ) -> Result<Pin<Box<dyn Stream<Item = Result<SubscriptionEvent, TransportError>>>>, TransportError> {
211 self.transport.subscribe(request).await
212 }
213}
214
215#[cfg(test)]
216mod tests {
217 use crate::types::{BigInt, CurrencyAmount};
218
219 use super::{transports::HTTPBuilder, types, XRPL};
220 #[test]
221 fn create_client() {
222 let _ = XRPL::new(
223 HTTPBuilder::default()
224 .with_endpoint("http://s1.ripple.com:51234/")
225 .unwrap()
226 .build()
227 .unwrap(),
228 );
229 }
230 #[tokio::test]
231 async fn account_info() {
232 let c = XRPL::new(
233 HTTPBuilder::default()
234 .with_endpoint("http://s1.ripple.com:51234/")
235 .unwrap()
236 .build()
237 .unwrap(),
238 );
239 let res = c
240 .account_info(types::account::AccountInfoRequest {
241 account: "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn".to_owned(),
242 strict: None,
243 queue: None,
244 ledger_info: types::LedgerInfo::default(),
245 signer_lists: None,
246 })
247 .await;
248 match res {
249 Err(e) => {
250 eprintln!("test failed: {:?}", e);
251 }
252 Ok(res) => {
253 assert_eq!(res.account_data.balance, CurrencyAmount::XRP(BigInt(9977)),);
254 }
255 }
256 }
257}