Skip to main content

soroban_cli/commands/tx/new/
path_payment_strict_send.rs

1use clap::Parser;
2
3use crate::{commands::tx, config::address, tx::builder, xdr};
4
5#[derive(Parser, Debug, Clone)]
6#[group(skip)]
7pub struct Cmd {
8    #[command(flatten)]
9    pub tx: tx::Args,
10    #[clap(flatten)]
11    pub op: Args,
12}
13
14#[derive(Debug, clap::Args, Clone)]
15pub struct Args {
16    /// Asset to send (pay with)
17    #[arg(long)]
18    pub send_asset: builder::Asset,
19
20    /// Amount of send asset to deduct from sender's account, in stroops. 1 stroop = 0.0000001 of the asset (e.g. 1 XLM = `10_000_000` stroops).
21    #[arg(long)]
22    pub send_amount: builder::Amount,
23
24    /// Account that receives the payment
25    #[arg(long)]
26    pub destination: address::UnresolvedMuxedAccount,
27
28    /// Asset that the destination will receive
29    #[arg(long)]
30    pub dest_asset: builder::Asset,
31
32    /// Minimum amount of destination asset that the destination account can receive. The operation will fail if this amount cannot be met.
33    #[arg(long)]
34    pub dest_min: builder::Amount,
35
36    /// List of intermediate assets for the payment path, comma-separated (up to 5 assets). Each asset should be in the format 'code:issuer' or 'native' for XLM.
37    #[arg(long, value_delimiter = ',')]
38    pub path: Vec<builder::Asset>,
39}
40
41impl TryFrom<&Cmd> for xdr::OperationBody {
42    type Error = tx::args::Error;
43    fn try_from(
44        Cmd {
45            tx,
46            op:
47                Args {
48                    send_asset,
49                    send_amount,
50                    destination,
51                    dest_asset,
52                    dest_min,
53                    path,
54                },
55        }: &Cmd,
56    ) -> Result<Self, Self::Error> {
57        // Validate path length (max 5 assets)
58        if path.len() > 5 {
59            return Err(tx::args::Error::InvalidPath(
60                "Path cannot contain more than 5 assets".to_string(),
61            ));
62        }
63
64        let path_assets: Result<Vec<xdr::Asset>, _> =
65            path.iter().map(|asset| tx.resolve_asset(asset)).collect();
66        let path_assets = path_assets?;
67
68        let path_vec = path_assets.try_into().map_err(|_| {
69            tx::args::Error::InvalidPath("Failed to convert path to VecM".to_string())
70        })?;
71
72        Ok(xdr::OperationBody::PathPaymentStrictSend(
73            xdr::PathPaymentStrictSendOp {
74                send_asset: tx.resolve_asset(send_asset)?,
75                send_amount: send_amount.into(),
76                destination: tx.resolve_muxed_address(destination)?,
77                dest_asset: tx.resolve_asset(dest_asset)?,
78                dest_min: dest_min.into(),
79                path: path_vec,
80            },
81        ))
82    }
83}