Skip to main content

xrpl/models/requests/
path_find.rs

1use alloc::borrow::Cow;
2use alloc::vec::Vec;
3use serde::{Deserialize, Serialize};
4use serde_with::skip_serializing_none;
5
6use crate::models::currency::Currency;
7use crate::models::{requests::RequestMethod, Model, PathStep};
8
9use super::{CommonFields, Request};
10
11/// A path is an array. Each member of a path is an object that specifies a step on that path.
12pub type Path<'a> = Vec<PathStep<'a>>;
13
14/// There are three different modes, or sub-commands, of
15/// the path_find command. Specify which one you want with
16/// the subcommand parameter:
17/// * create - Start sending pathfinding information
18/// * close - Stop sending pathfinding information
19/// * status - Info on the currently-open pathfinding request
20///
21/// See Path Find:
22/// `<https://xrpl.org/path_find.html>`
23#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
24#[serde(rename_all = "snake_case")]
25pub enum PathFindSubcommand {
26    #[default]
27    Create,
28    Close,
29    Status,
30}
31
32/// WebSocket API only! The path_find method searches for
33/// a path along which a transaction can possibly be made,
34/// and periodically sends updates when the path changes
35/// over time. For a simpl<'a>er version that is supported by
36/// JSON-RPC, see the ripple_path_find method. For payments
37/// occurring strictly in XRP, it is not necessary to find
38/// a path, because XRP can be sent directly to any account.
39///
40/// Although the rippled server tries to find the cheapest
41/// path or combination of paths for making a payment, it is
42/// not guaranteed that the paths returned by this method
43/// are, in fact, the best paths. Due to server load,
44/// pathfinding may not find the best results. Additionally,
45/// you should be careful with the pathfinding results from
46/// untrusted servers. A server could be modified to return
47/// less-than-optimal paths to earn money for its operators.
48/// If you do not have your own server that you can trust
49/// with pathfinding, you should compare the results of
50/// pathfinding from multiple servers run by different
51/// parties, to minimize the risk of a single server
52/// returning poor results. (Note: A server returning
53/// less-than-optimal results is not necessarily proof of
54/// malicious behavior; it could also be a symptom of heavy
55/// server load.)
56///
57/// See Path Find:
58/// `<https://xrpl.org/path_find.html>`
59#[skip_serializing_none]
60#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
61pub struct PathFind<'a> {
62    /// The common fields shared by all requests.
63    #[serde(flatten)]
64    pub common_fields: CommonFields<'a>,
65    /// Unique address of the account to find a path to.
66    /// (In other words, the account that would receive a payment.)
67    pub destination_account: Cow<'a, str>,
68    /// Currency Amount that the destination account would
69    /// receive in a transaction. Special case: New in: rippled 0.30.0
70    /// You can specify "-1" (for XRP) or provide -1 as the contents of
71    /// the value field (for non-XRP currencies). This requests a path
72    /// to deliver as much as possible, while spending no more than
73    /// the amount specified in send_max (if provided).
74    pub destination_amount: Currency<'a>,
75    /// Unique address of the account to find a path
76    /// from. (In other words, the account that would
77    /// be sending a payment.)
78    pub source_account: Cow<'a, str>,
79    /// Use "create" to send the create sub-command.
80    pub subcommand: PathFindSubcommand,
81    /// Array of arrays of objects, representing payment paths to check.
82    /// You can use this to keep updated on changes to particular paths
83    /// you already know about, or to check the overall cost to make a
84    /// payment along a certain path.
85    pub paths: Option<Vec<Path<'a>>>,
86    /// Currency Amount that would be spent in the transaction.
87    /// Not compatible with source_currencies.
88    pub send_max: Option<Currency<'a>>,
89}
90
91impl<'a> Model for PathFind<'a> {}
92
93impl<'a> Request<'a> for PathFind<'a> {
94    fn get_common_fields(&self) -> &CommonFields<'a> {
95        &self.common_fields
96    }
97
98    fn get_common_fields_mut(&mut self) -> &mut CommonFields<'a> {
99        &mut self.common_fields
100    }
101}
102
103impl<'a> PathFind<'a> {
104    pub fn new(
105        id: Option<Cow<'a, str>>,
106        destination_account: Cow<'a, str>,
107        destination_amount: Currency<'a>,
108        source_account: Cow<'a, str>,
109        subcommand: PathFindSubcommand,
110        paths: Option<Vec<Vec<PathStep<'a>>>>,
111        send_max: Option<Currency<'a>>,
112    ) -> Self {
113        Self {
114            common_fields: CommonFields {
115                command: RequestMethod::PathFind,
116                id,
117            },
118            subcommand,
119            source_account,
120            destination_account,
121            destination_amount,
122            send_max,
123            paths,
124        }
125    }
126}
127
128#[cfg(test)]
129mod tests {
130    use super::*;
131    use crate::models::currency::XRP;
132
133    #[test]
134    fn test_serde_round_trip() {
135        let req = PathFind::new(
136            Some("pf-1".into()),
137            "rDest11111111111111111111111111111".into(),
138            Currency::XRP(XRP::new()),
139            "rSrc111111111111111111111111111111".into(),
140            PathFindSubcommand::Create,
141            None,
142            Some(Currency::XRP(XRP::new())),
143        );
144        let serialized = serde_json::to_string(&req).unwrap();
145        let deserialized: PathFind = serde_json::from_str(&serialized).unwrap();
146        assert_eq!(req, deserialized);
147        assert!(serialized.contains("\"command\":\"path_find\""));
148        assert!(serialized.contains("\"subcommand\":\"create\""));
149    }
150
151    #[test]
152    fn test_subcommand_default() {
153        assert_eq!(PathFindSubcommand::default(), PathFindSubcommand::Create);
154    }
155}