Skip to main content

soroban_cli/commands/tx/new/
manage_sell_offer.rs

1use clap::Parser;
2
3use crate::{commands::tx, tx::builder, xdr};
4
5#[derive(Parser, Debug, Clone)]
6#[group(skip)]
7pub struct Cmd {
8    #[command(flatten)]
9    pub tx: tx::Args,
10
11    #[clap(flatten)]
12    pub op: Args,
13}
14
15#[derive(Debug, clap::Args, Clone)]
16pub struct Args {
17    /// Asset to sell
18    #[arg(long)]
19    pub selling: builder::Asset,
20
21    /// Asset to buy
22    #[arg(long)]
23    pub buying: builder::Asset,
24
25    /// Amount of selling asset to offer, in stroops. 1 stroop = 0.0000001 of the asset (e.g. 1 XLM = `10_000_000` stroops). Use `0` to remove the offer.
26    #[arg(long)]
27    pub amount: builder::Amount,
28
29    /// Price of 1 unit of selling asset in terms of buying asset as "numerator:denominator" (e.g., "1:2" means 0.5)
30    #[arg(long)]
31    pub price: String,
32
33    /// Offer ID. If 0, will create new offer. Otherwise, will update existing offer.
34    #[arg(long, default_value = "0")]
35    pub offer_id: i64,
36}
37
38impl TryFrom<&Cmd> for xdr::OperationBody {
39    type Error = tx::args::Error;
40    fn try_from(
41        Cmd {
42            tx,
43            op:
44                Args {
45                    selling,
46                    buying,
47                    amount,
48                    price,
49                    offer_id,
50                },
51        }: &Cmd,
52    ) -> Result<Self, Self::Error> {
53        let price_parts: Vec<&str> = price.split(':').collect();
54        if price_parts.len() != 2 {
55            return Err(tx::args::Error::InvalidPrice(price.clone()));
56        }
57
58        let n: i32 = price_parts[0]
59            .parse()
60            .map_err(|_| tx::args::Error::InvalidPrice(price.clone()))?;
61        let d: i32 = price_parts[1]
62            .parse()
63            .map_err(|_| tx::args::Error::InvalidPrice(price.clone()))?;
64
65        if d == 0 {
66            return Err(tx::args::Error::InvalidPrice(
67                "denominator cannot be zero".to_string(),
68            ));
69        }
70
71        Ok(xdr::OperationBody::ManageSellOffer(
72            xdr::ManageSellOfferOp {
73                selling: tx.resolve_asset(selling)?,
74                buying: tx.resolve_asset(buying)?,
75                amount: amount.into(),
76                price: xdr::Price { n, d },
77                offer_id: *offer_id,
78            },
79        ))
80    }
81}