soroban_cli/commands/
mod.rs1use std::str::FromStr;
2
3use async_trait::async_trait;
4use clap::{command, error::ErrorKind, CommandFactory, FromArgMatches, Parser};
5
6use crate::config;
7
8pub mod cache;
9pub mod completion;
10pub mod container;
11pub mod contract;
12pub mod env;
13pub mod events;
14pub mod global;
15pub mod keys;
16pub mod network;
17pub mod plugin;
18pub mod snapshot;
19pub mod tx;
20pub mod version;
21
22pub mod txn_result;
23
24pub const HEADING_RPC: &str = "Options (RPC)";
25pub const HEADING_GLOBAL: &str = "Options (Global)";
26const ABOUT: &str =
27 "Work seamlessly with Stellar accounts, contracts, and assets from the command line.
28
29- Generate and manage keys and accounts
30- Build, deploy, and interact with contracts
31- Deploy asset contracts
32- Stream events
33- Start local testnets
34- Decode, encode XDR
35- More!
36
37For additional information see:
38
39- Stellar Docs: https://developers.stellar.org
40- Smart Contract Docs: https://developers.stellar.org/docs/build/smart-contracts/overview
41- CLI Docs: https://developers.stellar.org/docs/tools/developer-tools/cli/stellar-cli";
42
43const LONG_ABOUT: &str = "
45
46To get started generate a new identity:
47
48 stellar keys generate alice
49
50Use keys with the `--source` flag in other commands.
51
52Commands that work with contracts are organized under the `contract` subcommand. List them:
53
54 stellar contract --help
55
56Use contracts like a CLI:
57
58 stellar contract invoke --id CCR6QKTWZQYW6YUJ7UP7XXZRLWQPFRV6SWBLQS4ZQOSAF4BOUD77OTE2 --source alice --network testnet -- --help
59
60Anything after the `--` double dash (the \"slop\") is parsed as arguments to the contract-specific CLI, generated on-the-fly from the contract schema. For the hello world example, with a function called `hello` that takes one string argument `to`, here's how you invoke it:
61
62 stellar contract invoke --id CCR6QKTWZQYW6YUJ7UP7XXZRLWQPFRV6SWBLQS4ZQOSAF4BOUD77OTE2 --source alice --network testnet -- hello --to world
63";
64
65#[derive(Parser, Debug)]
66#[command(
67 name = "stellar",
68 about = ABOUT,
69 version = version::long(),
70 long_about = ABOUT.to_string() + LONG_ABOUT,
71 disable_help_subcommand = true,
72)]
73pub struct Root {
74 #[clap(flatten)]
75 pub global_args: global::Args,
76
77 #[command(subcommand)]
78 pub cmd: Cmd,
79}
80
81impl Root {
82 pub fn new() -> Result<Self, Error> {
83 Self::try_parse().map_err(|e| {
84 if std::env::args().any(|s| s == "--list") {
85 let _ = plugin::ls::Cmd.run();
86 std::process::exit(0);
87 }
88
89 match e.kind() {
90 ErrorKind::InvalidSubcommand => match plugin::default::run() {
91 Ok(()) => Error::Clap(e),
92 Err(e) => Error::PluginDefault(e),
93 },
94 _ => Error::Clap(e),
95 }
96 })
97 }
98
99 pub fn from_arg_matches<I, T>(itr: I) -> Result<Self, clap::Error>
100 where
101 I: IntoIterator<Item = T>,
102 T: Into<std::ffi::OsString> + Clone,
103 {
104 Self::from_arg_matches_mut(&mut Self::command().get_matches_from(itr))
105 }
106
107 pub async fn run(&mut self) -> Result<(), Error> {
108 match &mut self.cmd {
109 Cmd::Completion(completion) => completion.run(),
110 Cmd::Plugin(plugin) => plugin.run(&self.global_args).await?,
111 Cmd::Contract(contract) => contract.run(&self.global_args).await?,
112 Cmd::Events(events) => events.run().await?,
113 Cmd::Xdr(xdr) => xdr.run()?,
114 Cmd::Network(network) => network.run(&self.global_args).await?,
115 Cmd::Container(container) => container.run(&self.global_args).await?,
116 Cmd::Snapshot(snapshot) => snapshot.run(&self.global_args).await?,
117 Cmd::Version(version) => version.run(),
118 Cmd::Keys(id) => id.run(&self.global_args).await?,
119 Cmd::Tx(tx) => tx.run(&self.global_args).await?,
120 Cmd::Cache(cache) => cache.run()?,
121 Cmd::Env(env) => env.run(&self.global_args)?,
122 }
123 Ok(())
124 }
125}
126
127impl FromStr for Root {
128 type Err = clap::Error;
129
130 fn from_str(s: &str) -> Result<Self, Self::Err> {
131 Self::from_arg_matches(s.split_whitespace())
132 }
133}
134
135#[derive(Parser, Debug)]
136pub enum Cmd {
137 #[command(subcommand)]
139 Contract(contract::Cmd),
140
141 Events(events::Cmd),
143
144 Env(env::Cmd),
153
154 #[command(subcommand)]
156 Keys(keys::Cmd),
157
158 #[command(subcommand)]
160 Network(network::Cmd),
161
162 #[command(subcommand)]
164 Container(container::Cmd),
165
166 #[command(subcommand)]
168 Snapshot(snapshot::Cmd),
169
170 #[command(subcommand)]
172 Tx(tx::Cmd),
173
174 Xdr(stellar_xdr::cli::Root),
176
177 #[command(long_about = completion::LONG_ABOUT)]
179 Completion(completion::Cmd),
180
181 #[command(subcommand)]
183 Cache(cache::Cmd),
184
185 Version(version::Cmd),
187
188 #[command(subcommand)]
190 Plugin(plugin::Cmd),
191}
192
193#[derive(thiserror::Error, Debug)]
194pub enum Error {
195 #[error(transparent)]
197 Contract(#[from] contract::Error),
198
199 #[error(transparent)]
200 Events(#[from] events::Error),
201
202 #[error(transparent)]
203 Keys(#[from] keys::Error),
204
205 #[error(transparent)]
206 Xdr(#[from] stellar_xdr::cli::Error),
207
208 #[error(transparent)]
209 Clap(#[from] clap::error::Error),
210
211 #[error(transparent)]
212 Plugin(#[from] plugin::Error),
213
214 #[error(transparent)]
215 PluginDefault(#[from] plugin::default::Error),
216
217 #[error(transparent)]
218 Network(#[from] network::Error),
219
220 #[error(transparent)]
221 Container(#[from] container::Error),
222
223 #[error(transparent)]
224 Snapshot(#[from] snapshot::Error),
225
226 #[error(transparent)]
227 Tx(#[from] tx::Error),
228
229 #[error(transparent)]
230 Cache(#[from] cache::Error),
231
232 #[error(transparent)]
233 Env(#[from] env::Error),
234}
235
236#[async_trait]
237pub trait NetworkRunnable {
238 type Error;
239 type Result;
240
241 async fn run_against_rpc_server(
242 &self,
243 global_args: Option<&global::Args>,
244 config: Option<&config::Args>,
245 ) -> Result<Self::Result, Self::Error>;
246}