soroban_cli/commands/tx/
send.rs

1use crate::print::Print;
2use async_trait::async_trait;
3use soroban_rpc::GetTransactionResponse;
4use std::ffi::OsString;
5
6use crate::{
7    commands::{global, NetworkRunnable},
8    config::{self, locator, network},
9};
10
11use stellar_xdr::curr;
12
13#[derive(thiserror::Error, Debug)]
14pub enum Error {
15    #[error(transparent)]
16    XdrArgs(#[from] super::xdr::Error),
17    #[error(transparent)]
18    Network(#[from] network::Error),
19    #[error(transparent)]
20    Config(#[from] config::Error),
21    #[error(transparent)]
22    Rpc(#[from] crate::rpc::Error),
23    #[error(transparent)]
24    SerdeJson(#[from] serde_json::Error),
25    #[error("xdr processing error: {0}")]
26    Xdr(#[from] curr::Error),
27}
28
29#[derive(Debug, clap::Parser, Clone)]
30#[group(skip)]
31/// Command to send a transaction envelope to the network
32/// e.g. `stellar tx send file.txt` or `cat file.txt | stellar tx send`
33pub struct Cmd {
34    /// Base-64 transaction envelope XDR or file containing XDR to decode, or stdin if empty
35    #[arg()]
36    pub tx_xdr: Option<OsString>,
37    #[clap(flatten)]
38    pub network: network::Args,
39    #[clap(flatten)]
40    pub locator: locator::Args,
41}
42
43impl Cmd {
44    pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
45        let response = self.run_against_rpc_server(Some(global_args), None).await?;
46        println!("{}", serde_json::to_string_pretty(&response)?);
47        Ok(())
48    }
49}
50
51#[async_trait]
52impl NetworkRunnable for Cmd {
53    type Error = Error;
54
55    type Result = GetTransactionResponse;
56    async fn run_against_rpc_server(
57        &self,
58        globals: Option<&global::Args>,
59        config: Option<&config::Args>,
60    ) -> Result<Self::Result, Self::Error> {
61        let network = if let Some(config) = config {
62            config.get_network()?
63        } else {
64            self.network.get(&self.locator)?
65        };
66        let client = network.rpc_client()?;
67        let tx_env = super::xdr::tx_envelope_from_input(&self.tx_xdr)?;
68
69        if let Ok(txn) = super::xdr::unwrap_envelope_v1(tx_env.clone()) {
70            let print = Print::new(globals.is_some_and(|g| g.quiet));
71            print.log_transaction(&txn, &network, true)?;
72        }
73
74        Ok(client.send_transaction_polling(&tx_env).await?)
75    }
76}