diff --git a/.github/workflows/audit_test.yml b/.github/workflows/audit_test.yml index ed37267..cf4334c 100644 --- a/.github/workflows/audit_test.yml +++ b/.github/workflows/audit_test.yml @@ -1,7 +1,7 @@ on: push: branches: - - develop + - dev pull_request: branches: - main diff --git a/.github/workflows/quality_test.yml b/.github/workflows/quality_test.yml index f553fea..1e01d77 100644 --- a/.github/workflows/quality_test.yml +++ b/.github/workflows/quality_test.yml @@ -1,7 +1,7 @@ on: push: branches: - - develop + - dev pull_request: branches: - main diff --git a/.github/workflows/unit_test.yml b/.github/workflows/unit_test.yml index 0d2e285..241f0c9 100644 --- a/.github/workflows/unit_test.yml +++ b/.github/workflows/unit_test.yml @@ -1,10 +1,11 @@ on: push: branches: - - develop + - dev pull_request: branches: - main + - dev name: Unit @@ -16,7 +17,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: stable + toolchain: nightly - uses: actions-rs/cargo@v1 with: command: build @@ -24,7 +25,7 @@ jobs: - uses: actions-rs/cargo@v1 with: command: build - args: --release --no-default-features --features core,models + args: --release --no-default-features --features core,models,net - uses: actions-rs/cargo@v1 with: command: test @@ -32,4 +33,4 @@ jobs: - uses: actions-rs/cargo@v1 with: command: test - args: --no-default-features --features core,models + args: --no-default-features --features core,models,net diff --git a/.gitignore b/.gitignore index 1ec67b5..338bdf8 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ Cargo.lock # Additional src/main.rs + +.DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c88321..15c526b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Performance Benchmarks ## [[Unreleased]] +- Examples + - Wallet from seed + - New wallet generation +- make `new` methods of models public ## [[v0.2.0-beta]] ### Added diff --git a/Cargo.toml b/Cargo.toml index 11b261e..3dd81c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,14 +29,14 @@ ed25519-dalek = "1.0.1" secp256k1 = { version = "0.27.0", default-features = false, features = [ "alloc", ] } -bs58 = { version = "0.4.0", default-features = false, features = [ +bs58 = { version = "0.5.0", default-features = false, features = [ "check", "alloc", ] } -indexmap = { version = "1.7.0", features = ["serde"] } +indexmap = { version = "2.0.0", features = ["serde"] } regex = { version = "1.5.4", default-features = false } -strum = { version = "0.24.1", default-features = false } -strum_macros = { version = "0.24.2", default-features = false } +strum = { version = "0.25.0", default-features = false } +strum_macros = { version = "0.25.2", default-features = false } crypto-bigint = { version = "0.5.1" } rust_decimal = { version = "1.17.0", default-features = false, features = [ "serde", @@ -46,38 +46,72 @@ chrono = { version = "0.4.19", default-features = false, features = [ "clock", ] } hex = { version = "0.4.3", default-features = false, features = ["alloc"] } -rand = { version = "0.8.4", default-features = false, features = ["getrandom"] } +rand = { version = "0.8.5", default-features = false, features = ["getrandom"] } serde = { version = "1.0.130", default-features = false, features = ["derive"] } serde_json = { version = "1.0.68", default-features = false, features = [ "alloc", ] } -serde_with = "2.3.1" +serde_with = "3.2.0" serde_repr = "0.1" zeroize = "1.5.7" -hashbrown = { version = "0.13.2", default-features = false, features = ["serde"] } +hashbrown = { version = "0.14.0", default-features = false, features = ["serde"] } fnv = { version = "1.0.7", default-features = false } derive-new = { version = "0.5.9", default-features = false } thiserror-no-std = "2.0.2" anyhow = { version ="1.0.69", default-features = false } +tokio = { version = "1.28.0", default-features = false, optional = true } +url = { version = "2.2.2", default-features = false, optional = true } +futures = { version = "0.3.28", default-features = false, optional = true } +rand_core = { version = "0.6.3", default-features = false } +tokio-tungstenite = { version = "0.20.0", optional = true } + +[dependencies.embedded-websocket] +# git version needed to use `framer_async` +git = "https://github.com/ninjasource/embedded-websocket" +version = "0.9.2" +rev = "8d87d46f46fa0c75e099ca8aad37e8d00c8854f8" +default-features = false [dev-dependencies] -criterion = "0.4.0" +xrpl-rust = { path = "." } +criterion = "0.5.1" cargo-husky = { version = "1.5.0", default-features = false, features = [ "user-hooks", ] } +tokio = { version = "1.28.2", features = ["full"] } +tokio-util = { version = "0.7.7", features = ["codec"] } +bytes = { version = "1.4.0", default-features = false } +futures = "0.3.28" +rand = "0.8.5" [[bench]] name = "benchmarks" harness = false [features] -default = ["std", "core", "models", "utils"] +default = ["std", "core", "models", "utils", "net"] models = ["core", "transactions", "requests", "ledger"] transactions = ["core", "amounts", "currencies"] requests = ["core", "amounts", "currencies"] ledger = ["core", "amounts", "currencies"] amounts = ["core"] currencies = ["core"] +net = ["url", "futures"] core = ["utils"] utils = [] -std = ["rand/std", "regex/std", "chrono/std", "rand/std_rng", "hex/std", "rust_decimal/std", "bs58/std", "serde/std", "indexmap/std", "secp256k1/std"] +std = [ + "embedded-websocket/std", + "tokio-tungstenite/native-tls", + "tokio/full", + "futures/std", + "rand/std", + "regex/std", + "chrono/std", + "rand/std_rng", + "hex/std", + "rust_decimal/std", + "bs58/std", + "serde/std", + "indexmap/std", + "secp256k1/std", +] diff --git a/examples/std/.gitignore b/examples/std/.gitignore new file mode 100644 index 0000000..1ec67b5 --- /dev/null +++ b/examples/std/.gitignore @@ -0,0 +1,20 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# Added by cargo +/target + +# VSCode +.vscode +.idea + +# Additional +src/main.rs diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml new file mode 100644 index 0000000..1e4a813 --- /dev/null +++ b/examples/std/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "std" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +xrpl-rust = { path = "../.." } + +[[bin]] +name = "wallet_from_seed" +path = "src/bin/wallet/wallet_from_seed.rs" +required-features = [ +] + +[[bin]] +name = "generate_wallet" +path = "src/bin/wallet/generate_wallet.rs" +required-features = [ +] + +[[bin]] +name = "send_request" +path = "src/bin/tokio/net/send_request.rs" +required-features = [ +] + +[[bin]] +name = "send_request" +path = "src/bin/transaction/sign_transaction.rs" +required-features = [ +] diff --git a/examples/std/src/bin/tokio/net/send_request.rs b/examples/std/src/bin/tokio/net/send_request.rs new file mode 100644 index 0000000..dc017cc --- /dev/null +++ b/examples/std/src/bin/tokio/net/send_request.rs @@ -0,0 +1,4 @@ +// TODO: add as soon as `AsyncWebsocketClient` is implemented +fn main() { + todo!() +} diff --git a/examples/std/src/bin/transaction/sign_transaction.rs b/examples/std/src/bin/transaction/sign_transaction.rs new file mode 100644 index 0000000..170c7df --- /dev/null +++ b/examples/std/src/bin/transaction/sign_transaction.rs @@ -0,0 +1,4 @@ +// TODO: add as soon as `sign` is implemented +fn main() { + todo!() +} diff --git a/examples/std/src/bin/wallet/generate_wallet.rs b/examples/std/src/bin/wallet/generate_wallet.rs new file mode 100644 index 0000000..4af7da7 --- /dev/null +++ b/examples/std/src/bin/wallet/generate_wallet.rs @@ -0,0 +1,7 @@ +use xrpl::wallet::Wallet; + +fn main() { + let wallet = Wallet::create(None).expect("Failed to generate new wallet"); + + println!("Wallet: {:?}", wallet); +} diff --git a/examples/std/src/bin/wallet/wallet_from_seed.rs b/examples/std/src/bin/wallet/wallet_from_seed.rs new file mode 100644 index 0000000..c561ecf --- /dev/null +++ b/examples/std/src/bin/wallet/wallet_from_seed.rs @@ -0,0 +1,9 @@ +use xrpl::wallet::Wallet; + +fn main() { + let wallet = Wallet::new("sEdVWgwiHxBmFoMGJBoPZf6H1XSLLGd", 0) + .expect("Failed to create wallet from seed"); + + assert_eq!(wallet.classic_address, "rsAhdjbE7YXqQtubcaSwb6xHn6mU2bSFHY"); + println!("Wallet: {:?}", wallet); +} diff --git a/src/_anyhow/mod.rs b/src/_anyhow/mod.rs index 345a3a8..7b4ab3e 100644 --- a/src/_anyhow/mod.rs +++ b/src/_anyhow/mod.rs @@ -2,6 +2,8 @@ #[macro_export] macro_rules! Err { ($err:expr $(,)?) => {{ + use alloc::string::ToString; + let error = $err.to_string().replace("\"", ""); let boxed_error = ::alloc::boxed::Box::new(error); let leaked_error: &'static str = ::alloc::boxed::Box::leak(boxed_error); diff --git a/src/asynch/clients/async_json_rpc_client.rs b/src/asynch/clients/async_json_rpc_client.rs new file mode 100644 index 0000000..614db2f --- /dev/null +++ b/src/asynch/clients/async_json_rpc_client.rs @@ -0,0 +1,2 @@ +// /// An async client for interacting with the rippled JSON RPC. +// pub struct AsyncJsonRpcClient {} diff --git a/src/asynch/clients/async_websocket_client.rs b/src/asynch/clients/async_websocket_client.rs new file mode 100644 index 0000000..7505ba0 --- /dev/null +++ b/src/asynch/clients/async_websocket_client.rs @@ -0,0 +1,283 @@ +use super::exceptions::XRPLWebsocketException; +use crate::Err; +use anyhow::Result; +use core::{ + fmt::{Debug, Display}, + marker::PhantomData, + ops::Deref, + pin::Pin, + task::Poll, +}; +use embedded_websocket::{ + framer_async::Framer as EmbeddedWebsocketFramer, Client as EmbeddedWebsocketClient, + WebSocket as EmbeddedWebsocket, +}; +use futures::{Sink, Stream}; +use rand_core::RngCore; +use url::Url; + +#[cfg(feature = "std")] +use tokio::net::TcpStream; +#[cfg(feature = "std")] +use tokio_tungstenite::{ + connect_async as tungstenite_connect_async, MaybeTlsStream as TungsteniteMaybeTlsStream, + WebSocketStream as TungsteniteWebsocketStream, +}; + +// Exports +pub use embedded_websocket::{ + framer_async::{ + FramerError as EmbeddedWebsocketFramerError, ReadResult as EmbeddedWebsocketReadMessageType, + }, + Error as EmbeddedWebsocketError, WebSocketCloseStatusCode as EmbeddedWebsocketCloseStatusCode, + WebSocketOptions as EmbeddedWebsocketOptions, + WebSocketSendMessageType as EmbeddedWebsocketSendMessageType, + WebSocketState as EmbeddedWebsocketState, +}; + +#[cfg(feature = "std")] +pub type AsyncWebsocketClientTungstenite = + AsyncWebsocketClient>, Status>; +pub type AsyncWebsocketClientEmbeddedWebsocket = + AsyncWebsocketClient, Status>; +#[cfg(feature = "std")] +pub use tokio_tungstenite::tungstenite::Message as TungsteniteMessage; + +pub struct WebsocketOpen; +pub struct WebsocketClosed; + +pub struct AsyncWebsocketClient { + inner: T, + status: PhantomData, +} + +impl AsyncWebsocketClient { + pub fn is_open(&self) -> bool { + core::any::type_name::() == core::any::type_name::() + } +} + +impl Sink for AsyncWebsocketClient +where + T: Sink + Unpin, + >::Error: Display, + I: serde::Serialize, +{ + type Error = anyhow::Error; + + fn poll_ready( + mut self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll> { + match Pin::new(&mut self.inner).poll_ready(cx) { + Poll::Ready(Ok(())) => Poll::Ready(Ok(())), + Poll::Ready(Err(error)) => Poll::Ready(Err!(error)), + Poll::Pending => Poll::Pending, + } + } + + fn start_send( + mut self: core::pin::Pin<&mut Self>, + item: I, + ) -> core::result::Result<(), Self::Error> { + match Pin::new(&mut self.inner).start_send(TungsteniteMessage::Text( + serde_json::to_string(&item).unwrap(), + )) { + // TODO: unwrap + Ok(()) => Ok(()), + Err(error) => Err!(error), + } + } + + fn poll_flush( + mut self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll> { + match Pin::new(&mut self.inner).poll_flush(cx) { + Poll::Ready(Ok(())) => Poll::Ready(Ok(())), + Poll::Ready(Err(error)) => Poll::Ready(Err!(error)), + Poll::Pending => Poll::Pending, + } + } + + fn poll_close( + mut self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll> { + match Pin::new(&mut self.inner).poll_close(cx) { + Poll::Ready(Ok(())) => Poll::Ready(Ok(())), + Poll::Ready(Err(error)) => Poll::Ready(Err!(error)), + Poll::Pending => Poll::Pending, + } + } +} + +impl Stream for AsyncWebsocketClient +where + T: Stream + Unpin, +{ + type Item = ::Item; + + fn poll_next( + mut self: Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> Poll> { + match Pin::new(&mut self.inner).poll_next(cx) { + Poll::Ready(Some(item)) => Poll::Ready(Some(item)), + Poll::Ready(None) => Poll::Ready(None), + Poll::Pending => Poll::Pending, + } + } +} + +#[cfg(feature = "std")] +impl + AsyncWebsocketClient< + TungsteniteWebsocketStream>, + WebsocketClosed, + > +{ + pub async fn open( + uri: Url, + ) -> Result< + AsyncWebsocketClient< + TungsteniteWebsocketStream>, + WebsocketOpen, + >, + > { + let (websocket_stream, _) = tungstenite_connect_async(uri).await.unwrap(); // TODO: unwrap + + Ok(AsyncWebsocketClient { + inner: websocket_stream, + status: PhantomData::, + }) + } +} + +impl + AsyncWebsocketClient, WebsocketClosed> +where + Rng: RngCore, +{ + pub async fn open<'a, B, E>( + stream: &mut (impl Stream> + Sink<&'a [u8], Error = E> + Unpin), + buffer: &'a mut [u8], + rng: Rng, + websocket_options: &EmbeddedWebsocketOptions<'_>, + ) -> Result< + AsyncWebsocketClient, WebsocketOpen>, + > + where + B: AsRef<[u8]>, + E: Debug, + { + let websocket = EmbeddedWebsocket::::new_client(rng); + let mut framer = EmbeddedWebsocketFramer::new(websocket); + framer + .connect(stream, buffer, websocket_options) + .await + .unwrap(); // TODO: unwrap + + Ok(AsyncWebsocketClient { + inner: framer, + status: PhantomData::, + }) + } +} + +impl AsyncWebsocketClient, WebsocketOpen> +where + Rng: RngCore, +{ + pub fn encode( + &mut self, + message_type: EmbeddedWebsocketSendMessageType, + end_of_message: bool, + from: &[u8], + to: &mut [u8], + ) -> Result + where + E: Debug, + { + let len = self + .inner + .encode::(message_type, end_of_message, from, to) + .unwrap(); // TODO: unwrap + + Ok(len) + } + + pub async fn send<'b, E, R: serde::Serialize>( + &mut self, + stream: &mut (impl Sink<&'b [u8], Error = E> + Unpin), + stream_buf: &'b mut [u8], + end_of_message: bool, + frame_buf: R, + ) -> Result<()> + where + E: Debug, + { + self.inner + .write( + stream, + stream_buf, + EmbeddedWebsocketSendMessageType::Binary, + end_of_message, + serde_json::to_vec(&frame_buf).unwrap().as_slice(), + ) // TODO: unwrap + .await + .unwrap(); // TODO: unwrap + + Ok(()) + } + + pub async fn close<'b, E>( + &mut self, + stream: &mut (impl Sink<&'b [u8], Error = E> + Unpin), + stream_buf: &'b mut [u8], + close_status: EmbeddedWebsocketCloseStatusCode, + status_description: Option<&str>, + ) -> Result<()> + where + E: Debug, + { + self.inner + .close(stream, stream_buf, close_status, status_description) + .await + .unwrap(); // TODO: unwrap + + Ok(()) + } + + pub async fn next<'a, B: Deref, E>( + &'a mut self, + stream: &mut (impl Stream> + Sink<&'a [u8], Error = E> + Unpin), + buffer: &'a mut [u8], + ) -> Option>> + // TODO: Change to Response as soon as implemented + where + E: Debug, + { + match self.inner.read(stream, buffer).await { + Some(Ok(read_result)) => Some(Ok(read_result)), + Some(Err(error)) => Some(Err!(XRPLWebsocketException::from(error))), + None => None, + } + } + + pub async fn try_next<'a, B: Deref, E>( + &'a mut self, + stream: &mut (impl Stream> + Sink<&'a [u8], Error = E> + Unpin), + buffer: &'a mut [u8], + ) -> Result>> + // TODO: Change to Response as soon as implemented + where + E: Debug, + { + match self.inner.read(stream, buffer).await { + Some(Ok(read_result)) => Ok(Some(read_result)), + Some(Err(error)) => Err!(XRPLWebsocketException::from(error)), + None => Ok(None), + } + } +} diff --git a/src/asynch/clients/exceptions.rs b/src/asynch/clients/exceptions.rs new file mode 100644 index 0000000..33f1b0f --- /dev/null +++ b/src/asynch/clients/exceptions.rs @@ -0,0 +1,44 @@ +use core::fmt::Debug; +use core::str::Utf8Error; +use embedded_websocket::framer_async::FramerError; +use thiserror_no_std::Error; + +#[derive(Debug, PartialEq, Eq, Error)] +pub enum XRPLWebsocketException { + #[error("Websocket is not open")] + NotOpen, + #[error("Failed to serialize XRPL request to string")] + RequestSerializationError, + // FramerError + #[error("I/O error: {0:?}")] + Io(E), + #[error("Frame too large (size: {0:?})")] + FrameTooLarge(usize), + #[error("Failed to interpret u8 to string (error: {0:?})")] + Utf8(Utf8Error), + #[error("Invalid HTTP header")] + HttpHeader, + #[error("Websocket error: {0:?}")] + WebSocket(embedded_websocket::Error), + #[error("Disconnected")] + Disconnected, + #[error("Read buffer is too small (size: {0:?})")] + RxBufferTooSmall(usize), +} + +impl From> for XRPLWebsocketException { + fn from(value: FramerError) -> Self { + match value { + FramerError::Io(e) => XRPLWebsocketException::Io(e), + FramerError::FrameTooLarge(e) => XRPLWebsocketException::FrameTooLarge(e), + FramerError::Utf8(e) => XRPLWebsocketException::Utf8(e), + FramerError::HttpHeader(_) => XRPLWebsocketException::HttpHeader, + FramerError::WebSocket(e) => XRPLWebsocketException::WebSocket(e), + FramerError::Disconnected => XRPLWebsocketException::Disconnected, + FramerError::RxBufferTooSmall(e) => XRPLWebsocketException::RxBufferTooSmall(e), + } + } +} + +#[cfg(feature = "std")] +impl alloc::error::Error for XRPLWebsocketException {} diff --git a/src/asynch/clients/mod.rs b/src/asynch/clients/mod.rs new file mode 100644 index 0000000..b5dbb46 --- /dev/null +++ b/src/asynch/clients/mod.rs @@ -0,0 +1,6 @@ +mod async_json_rpc_client; +mod async_websocket_client; +mod exceptions; + +pub use async_json_rpc_client::*; +pub use async_websocket_client::*; diff --git a/src/asynch/mod.rs b/src/asynch/mod.rs new file mode 100644 index 0000000..286b8f6 --- /dev/null +++ b/src/asynch/mod.rs @@ -0,0 +1,2 @@ +#[cfg(feature = "net")] +pub mod clients; diff --git a/src/lib.rs b/src/lib.rs index 58f3a23..ba014d9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,12 +19,15 @@ //! [XRP Ledger](https://xrpl.org/docs.html). #![no_std] #![allow(dead_code)] // Remove eventually +#![allow(incomplete_features)] +#![feature(async_fn_in_trait)] #[cfg(not(feature = "std"))] extern crate alloc; #[cfg(feature = "std")] extern crate std as alloc; +pub mod asynch; pub mod constants; #[cfg(feature = "core")] pub mod core; diff --git a/src/models/mod.rs b/src/models/mod.rs index b3c6a22..ff0bc5e 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -9,6 +9,7 @@ pub mod exceptions; #[cfg(feature = "ledger")] +#[allow(clippy::too_many_arguments)] pub mod ledger; pub mod model; #[cfg(feature = "requests")] diff --git a/src/models/requests/account_channels.rs b/src/models/requests/account_channels.rs index 705d5cd..a6f0ed9 100644 --- a/src/models/requests/account_channels.rs +++ b/src/models/requests/account_channels.rs @@ -76,7 +76,7 @@ impl<'a> Default for AccountChannels<'a> { impl<'a> Model for AccountChannels<'a> {} impl<'a> AccountChannels<'a> { - fn new( + pub fn new( account: &'a str, id: Option<&'a str>, ledger_hash: Option<&'a str>, diff --git a/src/models/requests/account_currencies.rs b/src/models/requests/account_currencies.rs index 35a9142..1edc900 100644 --- a/src/models/requests/account_currencies.rs +++ b/src/models/requests/account_currencies.rs @@ -50,7 +50,7 @@ impl<'a> Default for AccountCurrencies<'a> { impl<'a> Model for AccountCurrencies<'a> {} impl<'a> AccountCurrencies<'a> { - fn new( + pub fn new( account: &'a str, id: Option<&'a str>, ledger_hash: Option<&'a str>, diff --git a/src/models/requests/account_info.rs b/src/models/requests/account_info.rs index 4f2ca2d..038b06b 100644 --- a/src/models/requests/account_info.rs +++ b/src/models/requests/account_info.rs @@ -59,7 +59,7 @@ impl<'a> Default for AccountInfo<'a> { impl<'a> Model for AccountInfo<'a> {} impl<'a> AccountInfo<'a> { - fn new( + pub fn new( account: &'a str, id: Option<&'a str>, ledger_hash: Option<&'a str>, diff --git a/src/models/requests/account_lines.rs b/src/models/requests/account_lines.rs index d08e88f..8ca47b5 100644 --- a/src/models/requests/account_lines.rs +++ b/src/models/requests/account_lines.rs @@ -56,7 +56,7 @@ impl<'a> Default for AccountLines<'a> { impl<'a> Model for AccountLines<'a> {} impl<'a> AccountLines<'a> { - fn new( + pub fn new( account: &'a str, id: Option<&'a str>, ledger_hash: Option<&'a str>, diff --git a/src/models/requests/account_nfts.rs b/src/models/requests/account_nfts.rs index 2cf7fb3..faa2639 100644 --- a/src/models/requests/account_nfts.rs +++ b/src/models/requests/account_nfts.rs @@ -41,7 +41,12 @@ impl<'a> Default for AccountNfts<'a> { impl<'a> Model for AccountNfts<'a> {} impl<'a> AccountNfts<'a> { - fn new(account: &'a str, id: Option<&'a str>, limit: Option, marker: Option) -> Self { + pub fn new( + account: &'a str, + id: Option<&'a str>, + limit: Option, + marker: Option, + ) -> Self { Self { account, id, diff --git a/src/models/requests/account_objects.rs b/src/models/requests/account_objects.rs index 0868a20..24a7a0f 100644 --- a/src/models/requests/account_objects.rs +++ b/src/models/requests/account_objects.rs @@ -79,7 +79,7 @@ impl<'a> Default for AccountObjects<'a> { impl<'a> Model for AccountObjects<'a> {} impl<'a> AccountObjects<'a> { - fn new( + pub fn new( account: &'a str, id: Option<&'a str>, ledger_hash: Option<&'a str>, diff --git a/src/models/requests/account_offers.rs b/src/models/requests/account_offers.rs index 90500eb..d310d54 100644 --- a/src/models/requests/account_offers.rs +++ b/src/models/requests/account_offers.rs @@ -55,7 +55,7 @@ impl<'a> Default for AccountOffers<'a> { impl<'a> Model for AccountOffers<'a> {} impl<'a> AccountOffers<'a> { - fn new( + pub fn new( account: &'a str, id: Option<&'a str>, ledger_hash: Option<&'a str>, diff --git a/src/models/requests/account_tx.rs b/src/models/requests/account_tx.rs index d3c6310..25827af 100644 --- a/src/models/requests/account_tx.rs +++ b/src/models/requests/account_tx.rs @@ -71,7 +71,7 @@ impl<'a> Default for AccountTx<'a> { impl<'a> Model for AccountTx<'a> {} impl<'a> AccountTx<'a> { - fn new( + pub fn new( account: &'a str, id: Option<&'a str>, ledger_hash: Option<&'a str>, diff --git a/src/models/requests/book_offers.rs b/src/models/requests/book_offers.rs index 75551e4..e470a70 100644 --- a/src/models/requests/book_offers.rs +++ b/src/models/requests/book_offers.rs @@ -61,7 +61,7 @@ impl<'a> Default for BookOffers<'a> { impl<'a> Model for BookOffers<'a> {} impl<'a> BookOffers<'a> { - fn new( + pub fn new( taker_gets: Currency<'a>, taker_pays: Currency<'a>, id: Option<&'a str>, diff --git a/src/models/requests/channel_authorize.rs b/src/models/requests/channel_authorize.rs index 348eb7b..8024c20 100644 --- a/src/models/requests/channel_authorize.rs +++ b/src/models/requests/channel_authorize.rs @@ -3,8 +3,6 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; -use alloc::string::ToString; - use crate::models::requests::XRPLChannelAuthorizeException; use crate::{ constants::CryptoAlgorithm, @@ -120,7 +118,7 @@ impl<'a> ChannelAuthorizeError for ChannelAuthorize<'a> { } impl<'a> ChannelAuthorize<'a> { - fn new( + pub fn new( channel_id: &'a str, amount: &'a str, id: Option<&'a str>, diff --git a/src/models/requests/channel_verify.rs b/src/models/requests/channel_verify.rs index 4355e07..73fb1dc 100644 --- a/src/models/requests/channel_verify.rs +++ b/src/models/requests/channel_verify.rs @@ -43,7 +43,7 @@ impl<'a> Default for ChannelVerify<'a> { impl<'a> Model for ChannelVerify<'a> {} impl<'a> ChannelVerify<'a> { - fn new( + pub fn new( channel_id: &'a str, amount: &'a str, public_key: &'a str, diff --git a/src/models/requests/deposit_authorize.rs b/src/models/requests/deposit_authorize.rs index 21a4af4..087a00d 100644 --- a/src/models/requests/deposit_authorize.rs +++ b/src/models/requests/deposit_authorize.rs @@ -43,7 +43,7 @@ impl<'a> Default for DepositAuthorized<'a> { impl<'a> Model for DepositAuthorized<'a> {} impl<'a> DepositAuthorized<'a> { - fn new( + pub fn new( source_account: &'a str, destination_account: &'a str, id: Option<&'a str>, diff --git a/src/models/requests/fee.rs b/src/models/requests/fee.rs index a5507b3..8416a2e 100644 --- a/src/models/requests/fee.rs +++ b/src/models/requests/fee.rs @@ -32,7 +32,7 @@ impl<'a> Default for Fee<'a> { impl<'a> Model for Fee<'a> {} impl<'a> Fee<'a> { - fn new(id: Option<&'a str>) -> Self { + pub fn new(id: Option<&'a str>) -> Self { Self { id, command: RequestMethod::Fee, diff --git a/src/models/requests/gateway_balances.rs b/src/models/requests/gateway_balances.rs index 122ff42..ade9309 100644 --- a/src/models/requests/gateway_balances.rs +++ b/src/models/requests/gateway_balances.rs @@ -50,7 +50,7 @@ impl<'a> Default for GatewayBalances<'a> { impl<'a> Model for GatewayBalances<'a> {} impl<'a> GatewayBalances<'a> { - fn new( + pub fn new( account: &'a str, id: Option<&'a str>, strict: Option, diff --git a/src/models/requests/ledger.rs b/src/models/requests/ledger.rs index 76d2225..bc1eabe 100644 --- a/src/models/requests/ledger.rs +++ b/src/models/requests/ledger.rs @@ -76,7 +76,7 @@ impl<'a> Default for Ledger<'a> { impl<'a> Model for Ledger<'a> {} impl<'a> Ledger<'a> { - fn new( + pub fn new( id: Option<&'a str>, ledger_hash: Option<&'a str>, ledger_index: Option<&'a str>, diff --git a/src/models/requests/ledger_closed.rs b/src/models/requests/ledger_closed.rs index 1b76d32..e7b5d30 100644 --- a/src/models/requests/ledger_closed.rs +++ b/src/models/requests/ledger_closed.rs @@ -31,7 +31,7 @@ impl<'a> Default for LedgerClosed<'a> { impl<'a> Model for LedgerClosed<'a> {} impl<'a> LedgerClosed<'a> { - fn new(id: Option<&'a str>) -> Self { + pub fn new(id: Option<&'a str>) -> Self { Self { id, command: RequestMethod::LedgerClosed, diff --git a/src/models/requests/ledger_current.rs b/src/models/requests/ledger_current.rs index 93e6bfa..6ccfd04 100644 --- a/src/models/requests/ledger_current.rs +++ b/src/models/requests/ledger_current.rs @@ -31,7 +31,7 @@ impl<'a> Default for LedgerCurrent<'a> { impl<'a> Model for LedgerCurrent<'a> {} impl<'a> LedgerCurrent<'a> { - fn new(id: Option<&'a str>) -> Self { + pub fn new(id: Option<&'a str>) -> Self { Self { id, command: RequestMethod::LedgerCurrent, diff --git a/src/models/requests/ledger_data.rs b/src/models/requests/ledger_data.rs index e519767..362e429 100644 --- a/src/models/requests/ledger_data.rs +++ b/src/models/requests/ledger_data.rs @@ -50,7 +50,7 @@ impl<'a> Default for LedgerData<'a> { impl<'a> Model for LedgerData<'a> {} impl<'a> LedgerData<'a> { - fn new( + pub fn new( id: Option<&'a str>, ledger_hash: Option<&'a str>, ledger_index: Option<&'a str>, diff --git a/src/models/requests/ledger_entry.rs b/src/models/requests/ledger_entry.rs index a21bd5a..7885638 100644 --- a/src/models/requests/ledger_entry.rs +++ b/src/models/requests/ledger_entry.rs @@ -3,8 +3,6 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; -use alloc::string::ToString; - use crate::models::requests::XRPLLedgerEntryException; use crate::models::{requests::RequestMethod, Model}; @@ -178,7 +176,7 @@ impl<'a> LedgerEntryError for LedgerEntry<'a> { } impl<'a> LedgerEntry<'a> { - fn new( + pub fn new( id: Option<&'a str>, index: Option<&'a str>, account_root: Option<&'a str>, diff --git a/src/models/requests/manifest.rs b/src/models/requests/manifest.rs index 9705a6f..7a02e28 100644 --- a/src/models/requests/manifest.rs +++ b/src/models/requests/manifest.rs @@ -37,7 +37,7 @@ impl<'a> Default for Manifest<'a> { impl<'a> Model for Manifest<'a> {} impl<'a> Manifest<'a> { - fn new(public_key: &'a str, id: Option<&'a str>) -> Self { + pub fn new(public_key: &'a str, id: Option<&'a str>) -> Self { Self { public_key, id, diff --git a/src/models/requests/mod.rs b/src/models/requests/mod.rs index 9473949..297799d 100644 --- a/src/models/requests/mod.rs +++ b/src/models/requests/mod.rs @@ -17,6 +17,7 @@ pub mod ledger; pub mod ledger_closed; pub mod ledger_current; pub mod ledger_data; +#[allow(clippy::result_large_err)] pub mod ledger_entry; pub mod manifest; pub mod nft_buy_offers; @@ -25,6 +26,7 @@ pub mod no_ripple_check; pub mod path_find; pub mod ping; pub mod random; +pub mod responses; pub mod ripple_path_find; pub mod server_info; pub mod server_state; @@ -62,6 +64,7 @@ pub use no_ripple_check::*; pub use path_find::*; pub use ping::*; pub use random::*; +pub use responses::*; pub use ripple_path_find::*; pub use server_info::*; pub use server_state::*; diff --git a/src/models/requests/nft_buy_offers.rs b/src/models/requests/nft_buy_offers.rs index b34308d..3ecfa1e 100644 --- a/src/models/requests/nft_buy_offers.rs +++ b/src/models/requests/nft_buy_offers.rs @@ -42,7 +42,7 @@ impl<'a> Default for NftBuyOffers<'a> { impl<'a> Model for NftBuyOffers<'a> {} impl<'a> NftBuyOffers<'a> { - fn new( + pub fn new( nft_id: &'a str, ledger_hash: Option<&'a str>, ledger_index: Option<&'a str>, diff --git a/src/models/requests/nft_sell_offers.rs b/src/models/requests/nft_sell_offers.rs index 3527350..354cafd 100644 --- a/src/models/requests/nft_sell_offers.rs +++ b/src/models/requests/nft_sell_offers.rs @@ -26,7 +26,7 @@ impl<'a> Default for NftSellOffers<'a> { impl<'a> Model for NftSellOffers<'a> {} impl<'a> NftSellOffers<'a> { - fn new(nft_id: &'a str) -> Self { + pub fn new(nft_id: &'a str) -> Self { Self { nft_id, command: RequestMethod::NftSellOffers, diff --git a/src/models/requests/no_ripple_check.rs b/src/models/requests/no_ripple_check.rs index 5c52ef6..37f5f0b 100644 --- a/src/models/requests/no_ripple_check.rs +++ b/src/models/requests/no_ripple_check.rs @@ -73,7 +73,7 @@ impl<'a> Default for NoRippleCheck<'a> { impl<'a> Model for NoRippleCheck<'a> {} impl<'a> NoRippleCheck<'a> { - fn new( + pub fn new( account: &'a str, role: NoRippleCheckRole, id: Option<&'a str>, diff --git a/src/models/requests/path_find.rs b/src/models/requests/path_find.rs index 57bc751..0eedc29 100644 --- a/src/models/requests/path_find.rs +++ b/src/models/requests/path_find.rs @@ -105,7 +105,7 @@ impl<'a> Default for PathFind<'a> { impl<'a> Model for PathFind<'a> {} impl<'a> PathFind<'a> { - fn new( + pub fn new( subcommand: PathFindSubcommand, source_account: &'a str, destination_account: &'a str, diff --git a/src/models/requests/ping.rs b/src/models/requests/ping.rs index 24e1c68..9c10044 100644 --- a/src/models/requests/ping.rs +++ b/src/models/requests/ping.rs @@ -30,7 +30,7 @@ impl<'a> Default for Ping<'a> { impl<'a> Model for Ping<'a> {} impl<'a> Ping<'a> { - fn new(id: Option<&'a str>) -> Self { + pub fn new(id: Option<&'a str>) -> Self { Self { id, command: RequestMethod::Ping, diff --git a/src/models/requests/random.rs b/src/models/requests/random.rs index 8cf9919..0ecbfbd 100644 --- a/src/models/requests/random.rs +++ b/src/models/requests/random.rs @@ -31,7 +31,7 @@ impl<'a> Default for Random<'a> { impl<'a> Model for Random<'a> {} impl<'a> Random<'a> { - fn new(id: Option<&'a str>) -> Self { + pub fn new(id: Option<&'a str>) -> Self { Self { id, command: RequestMethod::Random, diff --git a/src/models/requests/responses/mod.rs b/src/models/requests/responses/mod.rs new file mode 100644 index 0000000..13671b7 --- /dev/null +++ b/src/models/requests/responses/mod.rs @@ -0,0 +1 @@ +pub trait Response {} diff --git a/src/models/requests/ripple_path_find.rs b/src/models/requests/ripple_path_find.rs index cbafd6e..77e4ce0 100644 --- a/src/models/requests/ripple_path_find.rs +++ b/src/models/requests/ripple_path_find.rs @@ -79,7 +79,7 @@ impl<'a> Default for RipplePathFind<'a> { impl<'a> Model for RipplePathFind<'a> {} impl<'a> RipplePathFind<'a> { - fn new( + pub fn new( source_account: &'a str, destination_account: &'a str, destination_amount: Currency<'a>, diff --git a/src/models/requests/server_info.rs b/src/models/requests/server_info.rs index 0308fbd..f869a4a 100644 --- a/src/models/requests/server_info.rs +++ b/src/models/requests/server_info.rs @@ -31,7 +31,7 @@ impl<'a> Default for ServerInfo<'a> { impl<'a> Model for ServerInfo<'a> {} impl<'a> ServerInfo<'a> { - fn new(id: Option<&'a str>) -> Self { + pub fn new(id: Option<&'a str>) -> Self { Self { id, command: RequestMethod::ServerInfo, diff --git a/src/models/requests/server_state.rs b/src/models/requests/server_state.rs index 2b7942c..8f1997b 100644 --- a/src/models/requests/server_state.rs +++ b/src/models/requests/server_state.rs @@ -36,7 +36,7 @@ impl<'a> Default for ServerState<'a> { impl<'a> Model for ServerState<'a> {} impl<'a> ServerState<'a> { - fn new(id: Option<&'a str>) -> Self { + pub fn new(id: Option<&'a str>) -> Self { Self { id, command: RequestMethod::ServerState, diff --git a/src/models/requests/submit.rs b/src/models/requests/submit.rs index 2fabd31..537125d 100644 --- a/src/models/requests/submit.rs +++ b/src/models/requests/submit.rs @@ -60,7 +60,7 @@ impl<'a> Default for Submit<'a> { impl<'a> Model for Submit<'a> {} impl<'a> Submit<'a> { - fn new(tx_blob: &'a str, id: Option<&'a str>, fail_hard: Option) -> Self { + pub fn new(tx_blob: &'a str, id: Option<&'a str>, fail_hard: Option) -> Self { Self { tx_blob, id, diff --git a/src/models/requests/submit_multisigned.rs b/src/models/requests/submit_multisigned.rs index 368207a..bb1d0cf 100644 --- a/src/models/requests/submit_multisigned.rs +++ b/src/models/requests/submit_multisigned.rs @@ -40,7 +40,7 @@ impl<'a> Default for SubmitMultisigned<'a> { impl<'a> Model for SubmitMultisigned<'a> {} impl<'a> SubmitMultisigned<'a> { - fn new(id: Option<&'a str>, fail_hard: Option) -> Self { + pub fn new(id: Option<&'a str>, fail_hard: Option) -> Self { Self { id, fail_hard, diff --git a/src/models/requests/subscribe.rs b/src/models/requests/subscribe.rs index 5c1efd0..60adf24 100644 --- a/src/models/requests/subscribe.rs +++ b/src/models/requests/subscribe.rs @@ -93,7 +93,7 @@ impl<'a> Default for Subscribe<'a> { impl<'a> Model for Subscribe<'a> {} impl<'a> Subscribe<'a> { - fn new( + pub fn new( id: Option<&'a str>, books: Option>>, streams: Option>, diff --git a/src/models/requests/transaction_entry.rs b/src/models/requests/transaction_entry.rs index cf0cf33..b668747 100644 --- a/src/models/requests/transaction_entry.rs +++ b/src/models/requests/transaction_entry.rs @@ -43,7 +43,7 @@ impl<'a> Default for TransactionEntry<'a> { impl<'a> Model for TransactionEntry<'a> {} impl<'a> TransactionEntry<'a> { - fn new( + pub fn new( tx_hash: &'a str, id: Option<&'a str>, ledger_hash: Option<&'a str>, diff --git a/src/models/requests/tx.rs b/src/models/requests/tx.rs index 9d3056f..2425536 100644 --- a/src/models/requests/tx.rs +++ b/src/models/requests/tx.rs @@ -46,7 +46,7 @@ impl<'a> Default for Tx<'a> { impl<'a> Model for Tx<'a> {} impl<'a> Tx<'a> { - fn new( + pub fn new( id: Option<&'a str>, binary: Option, min_ledger: Option, diff --git a/src/models/requests/unsubscribe.rs b/src/models/requests/unsubscribe.rs index d8ac3d9..8ffc821 100644 --- a/src/models/requests/unsubscribe.rs +++ b/src/models/requests/unsubscribe.rs @@ -75,7 +75,7 @@ impl<'a> Default for Unsubscribe<'a> { impl<'a> Model for Unsubscribe<'a> {} impl<'a> Unsubscribe<'a> { - fn new( + pub fn new( id: Option<&'a str>, books: Option>>, streams: Option>, diff --git a/src/models/transactions/account_delete.rs b/src/models/transactions/account_delete.rs index 6623b40..e30e1a0 100644 --- a/src/models/transactions/account_delete.rs +++ b/src/models/transactions/account_delete.rs @@ -121,7 +121,7 @@ impl<'a> Transaction for AccountDelete<'a> { } impl<'a> AccountDelete<'a> { - fn new( + pub fn new( account: &'a str, destination: &'a str, fee: Option>, diff --git a/src/models/transactions/account_set.rs b/src/models/transactions/account_set.rs index 8b37c14..3c9fad9 100644 --- a/src/models/transactions/account_set.rs +++ b/src/models/transactions/account_set.rs @@ -5,8 +5,6 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use serde_with::skip_serializing_none; use strum_macros::{AsRefStr, Display, EnumIter}; -use alloc::string::ToString; - use crate::models::amount::XRPAmount; use crate::models::transactions::XRPLAccountSetException; use crate::{ @@ -387,7 +385,7 @@ impl<'a> AccountSetError for AccountSet<'a> { } impl<'a> AccountSet<'a> { - fn new( + pub fn new( account: &'a str, fee: Option>, sequence: Option, diff --git a/src/models/transactions/check_cancel.rs b/src/models/transactions/check_cancel.rs index 26a8174..48bef9c 100644 --- a/src/models/transactions/check_cancel.rs +++ b/src/models/transactions/check_cancel.rs @@ -114,7 +114,7 @@ impl<'a> Transaction for CheckCancel<'a> { } impl<'a> CheckCancel<'a> { - fn new( + pub fn new( account: &'a str, check_id: &'a str, fee: Option>, diff --git a/src/models/transactions/check_cash.rs b/src/models/transactions/check_cash.rs index 58648d3..c51951f 100644 --- a/src/models/transactions/check_cash.rs +++ b/src/models/transactions/check_cash.rs @@ -4,8 +4,6 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; -use alloc::string::ToString; - use crate::models::amount::XRPAmount; use crate::models::transactions::XRPLCheckCashException; use crate::models::{ @@ -147,7 +145,7 @@ impl<'a> CheckCashError for CheckCash<'a> { } impl<'a> CheckCash<'a> { - fn new( + pub fn new( account: &'a str, check_id: &'a str, fee: Option>, diff --git a/src/models/transactions/check_create.rs b/src/models/transactions/check_create.rs index 772bbd1..b5c1f83 100644 --- a/src/models/transactions/check_create.rs +++ b/src/models/transactions/check_create.rs @@ -121,7 +121,7 @@ impl<'a> Transaction for CheckCreate<'a> { } impl<'a> CheckCreate<'a> { - fn new( + pub fn new( account: &'a str, destination: &'a str, send_max: Amount<'a>, diff --git a/src/models/transactions/deposit_preauth.rs b/src/models/transactions/deposit_preauth.rs index ceb42a5..0376f24 100644 --- a/src/models/transactions/deposit_preauth.rs +++ b/src/models/transactions/deposit_preauth.rs @@ -4,8 +4,6 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; -use alloc::string::ToString; - use crate::models::amount::XRPAmount; use crate::models::transactions::XRPLDepositPreauthException; use crate::models::{ @@ -141,7 +139,7 @@ impl<'a> DepositPreauthError for DepositPreauth<'a> { } impl<'a> DepositPreauth<'a> { - fn new( + pub fn new( account: &'a str, fee: Option>, sequence: Option, diff --git a/src/models/transactions/escrow_cancel.rs b/src/models/transactions/escrow_cancel.rs index 5bef7a5..42eadca 100644 --- a/src/models/transactions/escrow_cancel.rs +++ b/src/models/transactions/escrow_cancel.rs @@ -112,7 +112,7 @@ impl<'a> Transaction for EscrowCancel<'a> { } impl<'a> EscrowCancel<'a> { - fn new( + pub fn new( account: &'a str, owner: &'a str, offer_sequence: u32, diff --git a/src/models/transactions/escrow_create.rs b/src/models/transactions/escrow_create.rs index f5e3b10..32905e4 100644 --- a/src/models/transactions/escrow_create.rs +++ b/src/models/transactions/escrow_create.rs @@ -4,8 +4,6 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; -use alloc::string::ToString; - use crate::models::amount::XRPAmount; use crate::models::transactions::XRPLEscrowCreateException; use crate::models::{ @@ -152,7 +150,7 @@ impl<'a> EscrowCreateError for EscrowCreate<'a> { } impl<'a> EscrowCreate<'a> { - fn new( + pub fn new( account: &'a str, amount: XRPAmount<'a>, destination: &'a str, diff --git a/src/models/transactions/escrow_finish.rs b/src/models/transactions/escrow_finish.rs index 7f5f75e..2ba50e6 100644 --- a/src/models/transactions/escrow_finish.rs +++ b/src/models/transactions/escrow_finish.rs @@ -4,8 +4,6 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; -use alloc::string::ToString; - use crate::models::transactions::XRPLEscrowFinishException; use crate::models::{ amount::XRPAmount, @@ -144,7 +142,7 @@ impl<'a> EscrowFinishError for EscrowFinish<'a> { } impl<'a> EscrowFinish<'a> { - fn new( + pub fn new( account: &'a str, owner: &'a str, offer_sequence: u32, diff --git a/src/models/transactions/nftoken_accept_offer.rs b/src/models/transactions/nftoken_accept_offer.rs index 0b8f785..68f3e5f 100644 --- a/src/models/transactions/nftoken_accept_offer.rs +++ b/src/models/transactions/nftoken_accept_offer.rs @@ -6,8 +6,6 @@ use rust_decimal::Decimal; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; -use alloc::string::ToString; - use crate::models::amount::exceptions::XRPLAmountException; use crate::models::amount::XRPAmount; use crate::models::transactions::XRPLNFTokenAcceptOfferException; @@ -174,7 +172,7 @@ impl<'a> NFTokenAcceptOfferError for NFTokenAcceptOffer<'a> { } impl<'a> NFTokenAcceptOffer<'a> { - fn new( + pub fn new( account: &'a str, fee: Option>, sequence: Option, diff --git a/src/models/transactions/nftoken_burn.rs b/src/models/transactions/nftoken_burn.rs index 457d238..e332043 100644 --- a/src/models/transactions/nftoken_burn.rs +++ b/src/models/transactions/nftoken_burn.rs @@ -114,7 +114,7 @@ impl<'a> Transaction for NFTokenBurn<'a> { } impl<'a> NFTokenBurn<'a> { - fn new( + pub fn new( account: &'a str, nftoken_id: &'a str, fee: Option>, diff --git a/src/models/transactions/nftoken_cancel_offer.rs b/src/models/transactions/nftoken_cancel_offer.rs index 5c850cc..205a531 100644 --- a/src/models/transactions/nftoken_cancel_offer.rs +++ b/src/models/transactions/nftoken_cancel_offer.rs @@ -4,8 +4,6 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; -use alloc::string::ToString; - use crate::models::amount::XRPAmount; use crate::models::transactions::XRPLNFTokenCancelOfferException; use crate::models::{ @@ -139,7 +137,7 @@ impl<'a> NFTokenCancelOfferError for NFTokenCancelOffer<'a> { } impl<'a> NFTokenCancelOffer<'a> { - fn new( + pub fn new( account: &'a str, nftoken_offers: Vec<&'a str>, fee: Option>, diff --git a/src/models/transactions/nftoken_create_offer.rs b/src/models/transactions/nftoken_create_offer.rs index 658a061..b2b53c5 100644 --- a/src/models/transactions/nftoken_create_offer.rs +++ b/src/models/transactions/nftoken_create_offer.rs @@ -7,8 +7,6 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use serde_with::skip_serializing_none; use strum_macros::{AsRefStr, Display, EnumIter}; -use alloc::string::ToString; - use crate::models::{ model::Model, transactions::{Flag, Memo, Signer, Transaction, TransactionType}, @@ -255,7 +253,7 @@ impl<'a> NFTokenCreateOfferError for NFTokenCreateOffer<'a> { } impl<'a> NFTokenCreateOffer<'a> { - fn new( + pub fn new( account: &'a str, nftoken_id: &'a str, amount: Amount<'a>, diff --git a/src/models/transactions/nftoken_mint.rs b/src/models/transactions/nftoken_mint.rs index e61dbc0..b6fbe7b 100644 --- a/src/models/transactions/nftoken_mint.rs +++ b/src/models/transactions/nftoken_mint.rs @@ -5,8 +5,6 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use serde_with::skip_serializing_none; use strum_macros::{AsRefStr, Display, EnumIter}; -use alloc::string::ToString; - use crate::{ constants::{MAX_TRANSFER_FEE, MAX_URI_LENGTH}, models::{ @@ -237,7 +235,7 @@ impl<'a> NFTokenMintError for NFTokenMint<'a> { } impl<'a> NFTokenMint<'a> { - fn new( + pub fn new( account: &'a str, nftoken_taxon: u32, fee: Option>, diff --git a/src/models/transactions/offer_cancel.rs b/src/models/transactions/offer_cancel.rs index 643252a..560b62f 100644 --- a/src/models/transactions/offer_cancel.rs +++ b/src/models/transactions/offer_cancel.rs @@ -110,7 +110,7 @@ impl<'a> Transaction for OfferCancel<'a> { } impl<'a> OfferCancel<'a> { - fn new( + pub fn new( account: &'a str, offer_sequence: u32, fee: Option>, diff --git a/src/models/transactions/offer_create.rs b/src/models/transactions/offer_create.rs index 1acd33d..13b2175 100644 --- a/src/models/transactions/offer_create.rs +++ b/src/models/transactions/offer_create.rs @@ -174,7 +174,7 @@ impl<'a> Transaction for OfferCreate<'a> { } impl<'a> OfferCreate<'a> { - fn new( + pub fn new( account: &'a str, taker_gets: Amount<'a>, taker_pays: Amount<'a>, diff --git a/src/models/transactions/payment.rs b/src/models/transactions/payment.rs index 41c757a..3358fc4 100644 --- a/src/models/transactions/payment.rs +++ b/src/models/transactions/payment.rs @@ -11,7 +11,6 @@ use crate::models::{ transactions::{Flag, Memo, Signer, Transaction, TransactionType}, PathStep, }; -use alloc::string::ToString; use crate::Err; use crate::_serde::txn_flags; @@ -260,7 +259,7 @@ impl<'a> PaymentError for Payment<'a> { } impl<'a> Payment<'a> { - fn new( + pub fn new( account: &'a str, amount: Amount<'a>, destination: &'a str, diff --git a/src/models/transactions/payment_channel_claim.rs b/src/models/transactions/payment_channel_claim.rs index 61ccbd3..4a30a21 100644 --- a/src/models/transactions/payment_channel_claim.rs +++ b/src/models/transactions/payment_channel_claim.rs @@ -174,7 +174,7 @@ impl<'a> Transaction for PaymentChannelClaim<'a> { } impl<'a> PaymentChannelClaim<'a> { - fn new( + pub fn new( account: &'a str, channel: &'a str, fee: Option>, diff --git a/src/models/transactions/payment_channel_create.rs b/src/models/transactions/payment_channel_create.rs index 9188e8a..0b444b5 100644 --- a/src/models/transactions/payment_channel_create.rs +++ b/src/models/transactions/payment_channel_create.rs @@ -120,7 +120,7 @@ impl<'a> Transaction for PaymentChannelCreate<'a> { } impl<'a> PaymentChannelCreate<'a> { - fn new( + pub fn new( account: &'a str, amount: XRPAmount<'a>, destination: &'a str, diff --git a/src/models/transactions/payment_channel_fund.rs b/src/models/transactions/payment_channel_fund.rs index 4f9c3a3..7870a26 100644 --- a/src/models/transactions/payment_channel_fund.rs +++ b/src/models/transactions/payment_channel_fund.rs @@ -115,7 +115,7 @@ impl<'a> Transaction for PaymentChannelFund<'a> { } impl<'a> PaymentChannelFund<'a> { - fn new( + pub fn new( account: &'a str, channel: &'a str, amount: XRPAmount<'a>, diff --git a/src/models/transactions/pseudo_transactions/enable_amendment.rs b/src/models/transactions/pseudo_transactions/enable_amendment.rs index a7476a7..463ea2b 100644 --- a/src/models/transactions/pseudo_transactions/enable_amendment.rs +++ b/src/models/transactions/pseudo_transactions/enable_amendment.rs @@ -103,7 +103,7 @@ impl<'a> Transaction for EnableAmendment<'a> { } impl<'a> EnableAmendment<'a> { - fn new( + pub fn new( account: &'a str, amendment: &'a str, ledger_sequence: u32, diff --git a/src/models/transactions/pseudo_transactions/set_fee.rs b/src/models/transactions/pseudo_transactions/set_fee.rs index b1aeced..f378232 100644 --- a/src/models/transactions/pseudo_transactions/set_fee.rs +++ b/src/models/transactions/pseudo_transactions/set_fee.rs @@ -69,7 +69,7 @@ impl<'a> Transaction for SetFee<'a> { } impl<'a> SetFee<'a> { - fn new( + pub fn new( account: &'a str, base_fee: XRPAmount<'a>, reference_fee_units: u32, diff --git a/src/models/transactions/pseudo_transactions/unl_modify.rs b/src/models/transactions/pseudo_transactions/unl_modify.rs index b9a3d7f..8ce7248 100644 --- a/src/models/transactions/pseudo_transactions/unl_modify.rs +++ b/src/models/transactions/pseudo_transactions/unl_modify.rs @@ -78,7 +78,7 @@ impl<'a> Transaction for UNLModify<'a> { } impl<'a> UNLModify<'a> { - fn new( + pub fn new( account: &'a str, ledger_sequence: u32, unlmodify_disabling: UNLModifyDisabling, diff --git a/src/models/transactions/set_regular_key.rs b/src/models/transactions/set_regular_key.rs index 3869743..d651dc4 100644 --- a/src/models/transactions/set_regular_key.rs +++ b/src/models/transactions/set_regular_key.rs @@ -114,7 +114,7 @@ impl<'a> Transaction for SetRegularKey<'a> { } impl<'a> SetRegularKey<'a> { - fn new( + pub fn new( account: &'a str, fee: Option>, sequence: Option, diff --git a/src/models/transactions/signer_list_set.rs b/src/models/transactions/signer_list_set.rs index 8223c03..961269b 100644 --- a/src/models/transactions/signer_list_set.rs +++ b/src/models/transactions/signer_list_set.rs @@ -5,8 +5,6 @@ use derive_new::new; use serde::{ser::SerializeMap, Deserialize, Serialize}; use serde_with::skip_serializing_none; -use alloc::string::ToString; - use crate::models::transactions::XRPLSignerListSetException; use crate::models::{ amount::XRPAmount, @@ -226,7 +224,7 @@ impl<'a> SignerListSetError for SignerListSet<'a> { } impl<'a> SignerListSet<'a> { - fn new( + pub fn new( account: &'a str, signer_quorum: u32, fee: Option>, diff --git a/src/models/transactions/ticket_create.rs b/src/models/transactions/ticket_create.rs index 2efb723..3779eab 100644 --- a/src/models/transactions/ticket_create.rs +++ b/src/models/transactions/ticket_create.rs @@ -110,7 +110,7 @@ impl<'a> Transaction for TicketCreate<'a> { } impl<'a> TicketCreate<'a> { - fn new( + pub fn new( account: &'a str, ticket_count: u32, fee: Option>, diff --git a/src/models/transactions/trust_set.rs b/src/models/transactions/trust_set.rs index 5b0727d..3165cd3 100644 --- a/src/models/transactions/trust_set.rs +++ b/src/models/transactions/trust_set.rs @@ -162,7 +162,7 @@ impl<'a> Transaction for TrustSet<'a> { } impl<'a> TrustSet<'a> { - fn new( + pub fn new( account: &'a str, limit_amount: IssuedCurrencyAmount<'a>, fee: Option>, diff --git a/src/wallet/mod.rs b/src/wallet/mod.rs index 0d36f11..acc3bbb 100644 --- a/src/wallet/mod.rs +++ b/src/wallet/mod.rs @@ -18,7 +18,8 @@ use zeroize::Zeroize; /// /// See Cryptographic Keys: /// `` -struct Wallet { +#[derive(Debug)] +pub struct Wallet { /// The seed from which the public and private keys /// are derived. pub seed: String, diff --git a/tests/common.rs b/tests/common.rs deleted file mode 100644 index 7db0151..0000000 --- a/tests/common.rs +++ /dev/null @@ -1,3 +0,0 @@ -/// Setup common testing prerequisites here such as connecting a client -/// to a server or creating required files/directories if needed. -pub fn setup() {} diff --git a/tests/common/codec.rs b/tests/common/codec.rs new file mode 100644 index 0000000..7e07486 --- /dev/null +++ b/tests/common/codec.rs @@ -0,0 +1,35 @@ +use bytes::{BufMut, BytesMut}; +use std::io; +use tokio_util::codec::{Decoder, Encoder}; + +pub struct Codec {} + +impl Codec { + pub fn new() -> Self { + Codec {} + } +} + +impl Decoder for Codec { + type Item = BytesMut; + type Error = io::Error; + + fn decode(&mut self, buf: &mut BytesMut) -> Result, io::Error> { + if !buf.is_empty() { + let len = buf.len(); + Ok(Some(buf.split_to(len))) + } else { + Ok(None) + } + } +} + +impl Encoder<&[u8]> for Codec { + type Error = io::Error; + + fn encode(&mut self, data: &[u8], buf: &mut BytesMut) -> Result<(), io::Error> { + buf.reserve(data.len()); + buf.put(data); + Ok(()) + } +} diff --git a/tests/common/constants.rs b/tests/common/constants.rs new file mode 100644 index 0000000..fb33485 --- /dev/null +++ b/tests/common/constants.rs @@ -0,0 +1,2 @@ +pub const ECHO_WS_SERVER: &'static str = "ws://ws.vi-server.org/mirror/"; +pub const ECHO_WSS_SERVER: &'static str = "wss://ws.vi-server.org/mirror/"; diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..59ec33c --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,41 @@ +pub mod codec; +use xrpl::asynch::clients::{ + AsyncWebsocketClientEmbeddedWebsocket, AsyncWebsocketClientTungstenite, + EmbeddedWebsocketOptions, WebsocketOpen, +}; + +use tokio::net::TcpStream; +use tokio_util::codec::Framed; + +mod constants; +pub use constants::*; + +pub async fn connect_to_wss_tungstinite_echo() -> AsyncWebsocketClientTungstenite { + let websocket = AsyncWebsocketClientTungstenite::open(ECHO_WSS_SERVER.parse().unwrap()) + .await + .unwrap(); + assert!(websocket.is_open()); + + websocket +} + +pub async fn connect_to_ws_embedded_websocket_tokio_echo( + stream: &mut Framed, + buffer: &mut [u8], +) -> AsyncWebsocketClientEmbeddedWebsocket { + let rng = rand::thread_rng(); + let websocket_options = EmbeddedWebsocketOptions { + path: "/mirror", + host: "ws.vi-server.org", + origin: "http://ws.vi-server.org:80", + sub_protocols: None, + additional_headers: None, + }; + + let websocket = + AsyncWebsocketClientEmbeddedWebsocket::open(stream, buffer, rng, &websocket_options) + .await + .unwrap(); + + websocket +} diff --git a/tests/integration/clients/mod.rs b/tests/integration/clients/mod.rs new file mode 100644 index 0000000..4d25964 --- /dev/null +++ b/tests/integration/clients/mod.rs @@ -0,0 +1,76 @@ +use super::common::{ + codec::Codec, connect_to_ws_embedded_websocket_tokio_echo, connect_to_wss_tungstinite_echo, +}; +use futures::{SinkExt, TryStreamExt}; +use tokio_util::codec::Framed; +use xrpl::asynch::clients::{EmbeddedWebsocketReadMessageType, TungsteniteMessage}; +use xrpl::models::requests::AccountInfo; + +#[tokio::test] +async fn test_websocket_tungstenite_echo() { + let mut websocket = connect_to_wss_tungstinite_echo().await; + let account_info = AccountInfo::new( + "rJumr5e1HwiuV543H7bqixhtFreChWTaHH", + None, + None, + None, + None, + None, + None, + ); + + websocket.send(&account_info).await.unwrap(); + + while let Ok(Some(TungsteniteMessage::Text(response))) = websocket.try_next().await { + let account_info_echo: AccountInfo = serde_json::from_str(response.as_str()).unwrap(); + println!("account_info_echo: {:?}", account_info_echo); + assert_eq!(account_info, account_info_echo); + + break; + } +} + +#[tokio::test] +async fn test_embedded_websocket_echo() { + let tcp_stream = tokio::net::TcpStream::connect("ws.vi-server.org:80") + .await + .unwrap(); + let mut framed = Framed::new(tcp_stream, Codec::new()); + let mut buffer = [0u8; 4096]; + let mut websocket = connect_to_ws_embedded_websocket_tokio_echo(&mut framed, &mut buffer).await; + let account_info = AccountInfo::new( + "rJumr5e1HwiuV543H7bqixhtFreChWTaHH", + None, + None, + None, + None, + None, + None, + ); + websocket + .send(&mut framed, &mut buffer, false, &account_info) + .await + .unwrap(); + + let mut ping_counter = 0; + loop { + let message = websocket + .try_next(&mut framed, &mut buffer) + .await + .unwrap() + .unwrap(); + match message { + EmbeddedWebsocketReadMessageType::Binary(msg) => { + assert_eq!(serde_json::to_vec(&account_info).unwrap().as_slice(), msg); + break; + } + EmbeddedWebsocketReadMessageType::Ping(_) => { + ping_counter += 1; + if ping_counter > 1 { + panic!("Expected only one ping"); + } + } + _ => panic!("Expected binary message"), + } + } +} diff --git a/tests/integration/mod.rs b/tests/integration/mod.rs new file mode 100644 index 0000000..d951073 --- /dev/null +++ b/tests/integration/mod.rs @@ -0,0 +1,3 @@ +use super::common; + +mod clients; diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs new file mode 100644 index 0000000..8732ebc --- /dev/null +++ b/tests/integration_tests.rs @@ -0,0 +1,4 @@ +#![allow(dead_code)] // Remove eventually +mod common; + +mod integration;