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