soroban_cli/commands/tx/
send.rs1use 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)]
31pub struct Cmd {
34 #[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}