From d0c077bdad427cc85a098daec4867350a7e4ea35 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 25 Jul 2024 14:21:49 -0400 Subject: [PATCH] chore: reorganize config into separate module (#1479) --- cmd/crates/soroban-test/src/lib.rs | 3 +- cmd/crates/soroban-test/tests/it/config.rs | 3 +- .../tests/it/integration/hello_world.rs | 8 +- cmd/crates/soroban-test/tests/it/util.rs | 4 +- .../src/commands/cache/actionlog/ls.rs | 3 +- .../src/commands/cache/actionlog/read.rs | 3 +- cmd/soroban-cli/src/commands/cache/clean.rs | 3 +- cmd/soroban-cli/src/commands/cache/path.rs | 3 +- .../commands/contract/bindings/typescript.rs | 8 +- .../src/commands/contract/deploy/asset.rs | 4 +- .../src/commands/contract/deploy/wasm.rs | 6 +- .../src/commands/contract/extend.rs | 4 +- .../src/commands/contract/fetch.rs | 6 +- .../src/commands/contract/id/asset.rs | 4 +- .../src/commands/contract/id/wasm.rs | 4 +- .../src/commands/contract/inspect.rs | 2 +- .../src/commands/contract/install.rs | 6 +- .../src/commands/contract/invoke.rs | 8 +- cmd/soroban-cli/src/commands/contract/read.rs | 6 +- .../src/commands/contract/restore.rs | 4 +- cmd/soroban-cli/src/commands/events.rs | 6 +- cmd/soroban-cli/src/commands/keys/add.rs | 2 +- cmd/soroban-cli/src/commands/keys/fund.rs | 2 +- cmd/soroban-cli/src/commands/keys/generate.rs | 4 +- cmd/soroban-cli/src/commands/keys/show.rs | 2 +- cmd/soroban-cli/src/commands/mod.rs | 3 +- cmd/soroban-cli/src/commands/network/add.rs | 4 +- cmd/soroban-cli/src/commands/network/mod.rs | 177 +--------------- cmd/soroban-cli/src/commands/tx/hash.rs | 7 +- .../src/{commands => }/config/alias.rs | 0 .../src/{commands => }/config/data.rs | 0 .../src/{commands => }/config/locator.rs | 2 +- .../src/{commands => }/config/mod.rs | 5 +- cmd/soroban-cli/src/config/network.rs | 200 ++++++++++++++++++ .../src/config/network/passphrase.rs | 4 + .../src/{commands => }/config/secret.rs | 0 cmd/soroban-cli/src/get_spec.rs | 5 +- cmd/soroban-cli/src/lib.rs | 1 + 38 files changed, 269 insertions(+), 247 deletions(-) rename cmd/soroban-cli/src/{commands => }/config/alias.rs (100%) rename cmd/soroban-cli/src/{commands => }/config/data.rs (100%) rename cmd/soroban-cli/src/{commands => }/config/locator.rs (99%) rename cmd/soroban-cli/src/{commands => }/config/mod.rs (97%) create mode 100644 cmd/soroban-cli/src/config/network.rs create mode 100644 cmd/soroban-cli/src/config/network/passphrase.rs rename cmd/soroban-cli/src/{commands => }/config/secret.rs (100%) diff --git a/cmd/crates/soroban-test/src/lib.rs b/cmd/crates/soroban-test/src/lib.rs index 8df6a97c0..544e2d59e 100644 --- a/cmd/crates/soroban-test/src/lib.rs +++ b/cmd/crates/soroban-test/src/lib.rs @@ -30,7 +30,8 @@ use assert_fs::{fixture::FixtureError, prelude::PathChild, TempDir}; use fs_extra::dir::CopyOptions; use soroban_cli::{ - commands::{config, contract::invoke, global, keys, network, NetworkRunnable}, + commands::{contract::invoke, global, keys, NetworkRunnable}, + config::{self, network}, CommandParser, }; diff --git a/cmd/crates/soroban-test/tests/it/config.rs b/cmd/crates/soroban-test/tests/it/config.rs index 5704237ed..70dfaa693 100644 --- a/cmd/crates/soroban-test/tests/it/config.rs +++ b/cmd/crates/soroban-test/tests/it/config.rs @@ -3,7 +3,8 @@ use soroban_test::{AssertExt, TestEnv}; use std::{fs, path::Path}; use crate::util::{add_key, add_test_id, SecretKind, DEFAULT_SEED_PHRASE}; -use soroban_cli::commands::network::{self, LOCAL_NETWORK_PASSPHRASE}; +use soroban_cli::commands::network; +use soroban_cli::config::network::passphrase::LOCAL as LOCAL_NETWORK_PASSPHRASE; fn ls(sandbox: &TestEnv) -> Vec { sandbox diff --git a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs index ec0c843db..1c766095f 100644 --- a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs +++ b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs @@ -1,8 +1,10 @@ use predicates::boolean::PredicateBooleanExt; -use soroban_cli::commands::{ +use soroban_cli::{ + commands::{ + contract::{self, fetch}, + txn_result::TxnResult, + }, config::{locator, secret}, - contract::{self, fetch}, - txn_result::TxnResult, }; use soroban_rpc::GetLatestLedgerResponse; use soroban_test::{AssertExt, TestEnv, LOCAL_NETWORK_PASSPHRASE}; diff --git a/cmd/crates/soroban-test/tests/it/util.rs b/cmd/crates/soroban-test/tests/it/util.rs index 6bf5f8c22..f424ea1ae 100644 --- a/cmd/crates/soroban-test/tests/it/util.rs +++ b/cmd/crates/soroban-test/tests/it/util.rs @@ -1,8 +1,8 @@ use std::path::Path; -use soroban_cli::commands::{ +use soroban_cli::{ + commands::contract, config::{locator::KeyType, secret::Secret}, - contract, }; use soroban_test::{TestEnv, Wasm, TEST_ACCOUNT}; diff --git a/cmd/soroban-cli/src/commands/cache/actionlog/ls.rs b/cmd/soroban-cli/src/commands/cache/actionlog/ls.rs index cb7a958c6..360512bba 100644 --- a/cmd/soroban-cli/src/commands/cache/actionlog/ls.rs +++ b/cmd/soroban-cli/src/commands/cache/actionlog/ls.rs @@ -1,7 +1,6 @@ use clap::command; -use super::super::super::config::locator; -use crate::commands::config::data; +use crate::config::{data, locator}; #[derive(thiserror::Error, Debug)] pub enum Error { diff --git a/cmd/soroban-cli/src/commands/cache/actionlog/read.rs b/cmd/soroban-cli/src/commands/cache/actionlog/read.rs index 67b4358f1..4991ac6ef 100644 --- a/cmd/soroban-cli/src/commands/cache/actionlog/read.rs +++ b/cmd/soroban-cli/src/commands/cache/actionlog/read.rs @@ -1,7 +1,6 @@ use std::{fs, io, path::PathBuf}; -use super::super::super::config::locator; -use crate::commands::config::data; +use crate::config::{data, locator}; #[derive(thiserror::Error, Debug)] pub enum Error { diff --git a/cmd/soroban-cli/src/commands/cache/clean.rs b/cmd/soroban-cli/src/commands/cache/clean.rs index bea0a43d4..e2378aa6c 100644 --- a/cmd/soroban-cli/src/commands/cache/clean.rs +++ b/cmd/soroban-cli/src/commands/cache/clean.rs @@ -1,7 +1,6 @@ use std::{fs, io::ErrorKind}; -use super::super::config::locator; -use crate::commands::config::data; +use crate::config::{data, locator}; #[derive(thiserror::Error, Debug)] pub enum Error { diff --git a/cmd/soroban-cli/src/commands/cache/path.rs b/cmd/soroban-cli/src/commands/cache/path.rs index 337608735..a382516b9 100644 --- a/cmd/soroban-cli/src/commands/cache/path.rs +++ b/cmd/soroban-cli/src/commands/cache/path.rs @@ -1,5 +1,4 @@ -use super::super::config::locator; -use crate::commands::config::data; +use crate::config::{data, locator}; #[derive(thiserror::Error, Debug)] pub enum Error { diff --git a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs index b2b6c3b1c..84e2b1762 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs @@ -7,12 +7,10 @@ use stellar_strkey::DecodeError; use crate::wasm; use crate::{ - commands::{ - config::{self, locator}, - contract::fetch, - global, + commands::{contract::fetch, global, NetworkRunnable}, + config::{ + self, locator, network::{self, Network}, - NetworkRunnable, }, get_spec::{self, get_remote_contract_spec}, }; diff --git a/cmd/soroban-cli/src/commands/contract/deploy/asset.rs b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs index e912d2b98..98276a86d 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy/asset.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs @@ -13,11 +13,11 @@ use std::{array::TryFromSliceError, fmt::Debug, num::ParseIntError}; use crate::{ commands::{ - config::{self, data}, - global, network, + global, txn_result::{TxnEnvelopeResult, TxnResult}, NetworkRunnable, }, + config::{self, data, network}, rpc::{Client, Error as SorobanRpcError}, utils::{contract_id_hash_from_asset, parsing::parse_asset}, }; diff --git a/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs index b85b65bcc..4c1aa5d55 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs @@ -16,14 +16,14 @@ use soroban_env_host::{ }; use crate::commands::{ - config::{data, locator}, contract::{self, id::wasm::get_contract_id}, - global, network, + global, txn_result::{TxnEnvelopeResult, TxnResult}, NetworkRunnable, }; use crate::{ - commands::{config, contract::install, HEADING_RPC}, + commands::{contract::install, HEADING_RPC}, + config::{self, data, locator, network}, rpc::{self, Client}, utils, wasm, }; diff --git a/cmd/soroban-cli/src/commands/contract/extend.rs b/cmd/soroban-cli/src/commands/contract/extend.rs index 89bdc7620..03c7c70cf 100644 --- a/cmd/soroban-cli/src/commands/contract/extend.rs +++ b/cmd/soroban-cli/src/commands/contract/extend.rs @@ -10,11 +10,11 @@ use soroban_env_host::xdr::{ use crate::{ commands::{ - config::{self, data, locator}, - global, network, + global, txn_result::{TxnEnvelopeResult, TxnResult}, NetworkRunnable, }, + config::{self, data, locator, network}, key, rpc::{self, Client}, wasm, Pwd, diff --git a/cmd/soroban-cli/src/commands/contract/fetch.rs b/cmd/soroban-cli/src/commands/contract/fetch.rs index 42f474558..7c6c84cb1 100644 --- a/cmd/soroban-cli/src/commands/contract/fetch.rs +++ b/cmd/soroban-cli/src/commands/contract/fetch.rs @@ -19,9 +19,11 @@ use soroban_env_host::{ use soroban_spec::read::FromWasmError; use stellar_strkey::DecodeError; -use super::super::config::{self, locator}; -use crate::commands::network::{self, Network}; use crate::commands::{global, NetworkRunnable}; +use crate::config::{ + self, locator, + network::{self, Network}, +}; use crate::{ rpc::{self, Client}, Pwd, diff --git a/cmd/soroban-cli/src/commands/contract/id/asset.rs b/cmd/soroban-cli/src/commands/contract/id/asset.rs index e036b7939..31b55f8d1 100644 --- a/cmd/soroban-cli/src/commands/contract/id/asset.rs +++ b/cmd/soroban-cli/src/commands/contract/id/asset.rs @@ -1,6 +1,6 @@ use clap::{arg, command, Parser}; -use crate::commands::config; +use crate::config; use crate::utils::contract_id_hash_from_asset; use crate::utils::parsing::parse_asset; @@ -20,7 +20,7 @@ pub enum Error { #[error(transparent)] ParseError(#[from] crate::utils::parsing::Error), #[error(transparent)] - ConfigError(#[from] crate::commands::config::Error), + ConfigError(#[from] config::Error), #[error(transparent)] Xdr(#[from] soroban_env_host::xdr::Error), } diff --git a/cmd/soroban-cli/src/commands/contract/id/wasm.rs b/cmd/soroban-cli/src/commands/contract/id/wasm.rs index 9c02f07d2..14824b145 100644 --- a/cmd/soroban-cli/src/commands/contract/id/wasm.rs +++ b/cmd/soroban-cli/src/commands/contract/id/wasm.rs @@ -5,7 +5,7 @@ use soroban_env_host::xdr::{ HashIdPreimageContractId, Limits, PublicKey, ScAddress, Uint256, WriteXdr, }; -use crate::commands::config; +use crate::config; #[derive(Parser, Debug, Clone)] #[group(skip)] @@ -22,7 +22,7 @@ pub enum Error { #[error(transparent)] ParseError(#[from] crate::utils::parsing::Error), #[error(transparent)] - ConfigError(#[from] crate::commands::config::Error), + ConfigError(#[from] config::Error), #[error(transparent)] Xdr(#[from] xdr::Error), #[error("cannot parse salt {0}")] diff --git a/cmd/soroban-cli/src/commands/contract/inspect.rs b/cmd/soroban-cli/src/commands/contract/inspect.rs index e66bf83fd..36a1a2302 100644 --- a/cmd/soroban-cli/src/commands/contract/inspect.rs +++ b/cmd/soroban-cli/src/commands/contract/inspect.rs @@ -5,7 +5,7 @@ use std::{fmt::Debug, path::PathBuf}; use tracing::debug; use super::SpecOutput; -use crate::{commands::config::locator, wasm}; +use crate::{config::locator, wasm}; #[derive(Parser, Debug, Clone)] #[group(skip)] diff --git a/cmd/soroban-cli/src/commands/contract/install.rs b/cmd/soroban-cli/src/commands/contract/install.rs index d7ebef16d..9d2e474a3 100644 --- a/cmd/soroban-cli/src/commands/contract/install.rs +++ b/cmd/soroban-cli/src/commands/contract/install.rs @@ -11,12 +11,12 @@ use soroban_env_host::xdr::{ }; use super::restore; -use crate::commands::network; use crate::commands::txn_result::{TxnEnvelopeResult, TxnResult}; -use crate::commands::{config::data, global, NetworkRunnable}; +use crate::commands::{global, NetworkRunnable}; +use crate::config::{self, data, network}; use crate::key; use crate::rpc::{self, Client}; -use crate::{commands::config, utils, wasm}; +use crate::{utils, wasm}; const CONTRACT_META_SDK_KEY: &str = "rssdkver"; const PUBLIC_NETWORK_PASSPHRASE: &str = "Public Global Stellar Network ; September 2015"; diff --git a/cmd/soroban-cli/src/commands/contract/invoke.rs b/cmd/soroban-cli/src/commands/contract/invoke.rs index 22462cbcb..041613ba2 100644 --- a/cmd/soroban-cli/src/commands/contract/invoke.rs +++ b/cmd/soroban-cli/src/commands/contract/invoke.rs @@ -23,15 +23,13 @@ use soroban_env_host::{ use soroban_spec::read::FromWasmError; -use super::super::{ - config::{self, locator}, - events, -}; +use super::super::events; use crate::commands::txn_result::{TxnEnvelopeResult, TxnResult}; use crate::commands::NetworkRunnable; use crate::get_spec::{self, get_remote_contract_spec}; use crate::{ - commands::{config::data, global, network}, + commands::global, + config::{self, data, locator, network}, rpc, Pwd, }; use soroban_spec_tools::{contract, Spec}; diff --git a/cmd/soroban-cli/src/commands/contract/read.rs b/cmd/soroban-cli/src/commands/contract/read.rs index 70e2bd09e..bef3f3737 100644 --- a/cmd/soroban-cli/src/commands/contract/read.rs +++ b/cmd/soroban-cli/src/commands/contract/read.rs @@ -13,10 +13,8 @@ use soroban_env_host::{ }; use crate::{ - commands::{ - config::{self, locator}, - global, NetworkRunnable, - }, + commands::{global, NetworkRunnable}, + config::{self, locator}, key, rpc::{self, Client, FullLedgerEntries, FullLedgerEntry}, }; diff --git a/cmd/soroban-cli/src/commands/contract/restore.rs b/cmd/soroban-cli/src/commands/contract/restore.rs index 2a6669920..192af3140 100644 --- a/cmd/soroban-cli/src/commands/contract/restore.rs +++ b/cmd/soroban-cli/src/commands/contract/restore.rs @@ -11,12 +11,12 @@ use stellar_strkey::DecodeError; use crate::{ commands::{ - config::{self, data, locator}, contract::extend, - global, network, + global, txn_result::{TxnEnvelopeResult, TxnResult}, NetworkRunnable, }, + config::{self, data, locator, network}, key, rpc::{self, Client}, wasm, Pwd, diff --git a/cmd/soroban-cli/src/commands/events.rs b/cmd/soroban-cli/src/commands/events.rs index e9f3ba645..a755c33d0 100644 --- a/cmd/soroban-cli/src/commands/events.rs +++ b/cmd/soroban-cli/src/commands/events.rs @@ -3,10 +3,8 @@ use std::io; use soroban_env_host::xdr::{self, Limits, ReadXdr}; -use super::{ - config::{self, locator}, - global, network, NetworkRunnable, -}; +use super::{global, NetworkRunnable}; +use crate::config::{self, locator, network}; use crate::rpc; #[derive(Parser, Debug, Clone)] diff --git a/cmd/soroban-cli/src/commands/keys/add.rs b/cmd/soroban-cli/src/commands/keys/add.rs index 2868c7371..d8f528bae 100644 --- a/cmd/soroban-cli/src/commands/keys/add.rs +++ b/cmd/soroban-cli/src/commands/keys/add.rs @@ -1,6 +1,6 @@ use clap::command; -use super::super::config::{locator, secret}; +use crate::config::{locator, secret}; #[derive(thiserror::Error, Debug)] pub enum Error { diff --git a/cmd/soroban-cli/src/commands/keys/fund.rs b/cmd/soroban-cli/src/commands/keys/fund.rs index b6c088f13..d7100c6cb 100644 --- a/cmd/soroban-cli/src/commands/keys/fund.rs +++ b/cmd/soroban-cli/src/commands/keys/fund.rs @@ -1,6 +1,6 @@ use clap::command; -use crate::commands::network; +use crate::config::network; use super::address; diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index 5c6c119ca..16e6a7fdb 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -1,9 +1,7 @@ use clap::{arg, command}; -use crate::commands::network; - use super::super::config::{ - locator, + locator, network, secret::{self, Secret}, }; diff --git a/cmd/soroban-cli/src/commands/keys/show.rs b/cmd/soroban-cli/src/commands/keys/show.rs index b99478cbc..58c47740c 100644 --- a/cmd/soroban-cli/src/commands/keys/show.rs +++ b/cmd/soroban-cli/src/commands/keys/show.rs @@ -1,6 +1,6 @@ use clap::arg; -use super::super::config::{locator, secret}; +use crate::config::{locator, secret}; #[derive(thiserror::Error, Debug)] pub enum Error { diff --git a/cmd/soroban-cli/src/commands/mod.rs b/cmd/soroban-cli/src/commands/mod.rs index a9f10bdd8..081439254 100644 --- a/cmd/soroban-cli/src/commands/mod.rs +++ b/cmd/soroban-cli/src/commands/mod.rs @@ -3,9 +3,10 @@ use std::str::FromStr; use async_trait::async_trait; use clap::{command, error::ErrorKind, CommandFactory, FromArgMatches, Parser}; +use crate::config; + pub mod cache; pub mod completion; -pub mod config; pub mod contract; pub mod events; pub mod global; diff --git a/cmd/soroban-cli/src/commands/network/add.rs b/cmd/soroban-cli/src/commands/network/add.rs index b6a2ddd38..20b1afa7b 100644 --- a/cmd/soroban-cli/src/commands/network/add.rs +++ b/cmd/soroban-cli/src/commands/network/add.rs @@ -1,4 +1,4 @@ -use super::super::config::{locator, secret}; +use crate::config::{locator, network, secret}; use clap::command; #[derive(thiserror::Error, Debug)] @@ -17,7 +17,7 @@ pub struct Cmd { pub name: String, #[command(flatten)] - pub network: super::Network, + pub network: network::Network, #[command(flatten)] pub config_locator: locator::Args, diff --git a/cmd/soroban-cli/src/commands/network/mod.rs b/cmd/soroban-cli/src/commands/network/mod.rs index 1c34f92c8..d0b4f32a3 100644 --- a/cmd/soroban-cli/src/commands/network/mod.rs +++ b/cmd/soroban-cli/src/commands/network/mod.rs @@ -1,20 +1,9 @@ -use std::str::FromStr; +use clap::Parser; -use clap::{arg, Parser}; -use phf::phf_map; -use serde::{Deserialize, Serialize}; -use serde_json::Value; -use stellar_strkey::ed25519::PublicKey; - -use crate::{ - commands::HEADING_RPC, - rpc::{self, Client}, -}; +use crate::rpc::{self}; use super::config::locator; -pub const LOCAL_NETWORK_PASSPHRASE: &str = "Standalone Network ; February 2017"; - pub mod add; pub mod container; pub mod ls; @@ -115,165 +104,3 @@ impl Cmd { Ok(()) } } - -#[derive(Debug, clap::Args, Clone, Default)] -#[group(skip)] -pub struct Args { - /// RPC server endpoint - #[arg( - long = "rpc-url", - requires = "network_passphrase", - required_unless_present = "network", - env = "STELLAR_RPC_URL", - help_heading = HEADING_RPC, - )] - pub rpc_url: Option, - /// Network passphrase to sign the transaction sent to the rpc server - #[arg( - long = "network-passphrase", - requires = "rpc_url", - required_unless_present = "network", - env = "STELLAR_NETWORK_PASSPHRASE", - help_heading = HEADING_RPC, - )] - pub network_passphrase: Option, - /// Name of network to use from config - #[arg( - long, - required_unless_present = "rpc_url", - env = "STELLAR_NETWORK", - help_heading = HEADING_RPC, - )] - pub network: Option, -} - -impl Args { - pub fn get(&self, locator: &locator::Args) -> Result { - if let Some(name) = self.network.as_deref() { - if let Ok(network) = locator.read_network(name) { - return Ok(network); - } - } - if let (Some(rpc_url), Some(network_passphrase)) = - (self.rpc_url.clone(), self.network_passphrase.clone()) - { - Ok(Network { - rpc_url, - network_passphrase, - }) - } else { - Err(Error::Network) - } - } -} - -#[derive(Debug, clap::Args, Serialize, Deserialize, Clone)] -#[group(skip)] -pub struct Network { - /// RPC server endpoint - #[arg( - long = "rpc-url", - env = "STELLAR_RPC_URL", - help_heading = HEADING_RPC, - )] - pub rpc_url: String, - /// Network passphrase to sign the transaction sent to the rpc server - #[arg( - long, - env = "STELLAR_NETWORK_PASSPHRASE", - help_heading = HEADING_RPC, - )] - pub network_passphrase: String, -} - -impl Network { - pub async fn helper_url(&self, addr: &str) -> Result { - use http::Uri; - tracing::debug!("address {addr:?}"); - let rpc_uri = Uri::from_str(&self.rpc_url) - .map_err(|_| Error::InvalidUrl(self.rpc_url.to_string()))?; - if self.network_passphrase.as_str() == LOCAL_NETWORK_PASSPHRASE { - let auth = rpc_uri.authority().unwrap().clone(); - let scheme = rpc_uri.scheme_str().unwrap(); - Ok(Uri::builder() - .authority(auth) - .scheme(scheme) - .path_and_query(format!("/friendbot?addr={addr}")) - .build()?) - } else { - let client = Client::new(&self.rpc_url)?; - let network = client.get_network().await?; - tracing::debug!("network {network:?}"); - let uri = client.friendbot_url().await?; - tracing::debug!("URI {uri:?}"); - Uri::from_str(&format!("{uri}?addr={addr}")).map_err(|e| { - tracing::error!("{e}"); - Error::InvalidUrl(uri.to_string()) - }) - } - } - - #[allow(clippy::similar_names)] - pub async fn fund_address(&self, addr: &PublicKey) -> Result<(), Error> { - let uri = self.helper_url(&addr.to_string()).await?; - tracing::debug!("URL {uri:?}"); - let response = match uri.scheme_str() { - Some("http") => hyper::Client::new().get(uri.clone()).await?, - Some("https") => { - let https = hyper_tls::HttpsConnector::new(); - hyper::Client::builder() - .build::<_, hyper::Body>(https) - .get(uri.clone()) - .await? - } - _ => { - return Err(Error::InvalidUrl(uri.to_string())); - } - }; - let body = hyper::body::to_bytes(response.into_body()).await?; - let res = serde_json::from_slice::(&body) - .map_err(|e| Error::FailedToParseJSON(uri.to_string(), e))?; - tracing::debug!("{res:#?}"); - if let Some(detail) = res.get("detail").and_then(Value::as_str) { - if detail.contains("createAccountAlreadyExist") { - eprintln!("Account already exists"); - } - } else if res.get("successful").is_none() { - return Err(Error::InproperResponse(res.to_string())); - } - Ok(()) - } - - pub fn rpc_uri(&self) -> Result { - http::Uri::from_str(&self.rpc_url).map_err(|_| Error::InvalidUrl(self.rpc_url.to_string())) - } -} - -pub static DEFAULTS: phf::Map<&'static str, (&'static str, &'static str)> = phf_map! { - "local" => ( - "http://localhost:8000/rpc", - "Standalone Network ; February 2017", - ), - "futurenet" => ( - "https://rpc-futurenet.stellar.org:443", - "Test SDF Future Network ; October 2022", - ), - "testnet" => ( - "https://soroban-testnet.stellar.org", - "Test SDF Network ; September 2015", - ), - "mainnet" => ( - "Bring Your Own: https://developers.stellar.org/docs/data/rpc/rpc-providers", - "Public Global Stellar Network ; September 2015", - ), -}; - -impl From<&(&str, &str)> for Network { - /// Convert the return value of `DEFAULTS.get()` into a Network - fn from(n: &(&str, &str)) -> Self { - Self { - rpc_url: n.0.to_string(), - network_passphrase: n.1.to_string(), - } - } -} diff --git a/cmd/soroban-cli/src/commands/tx/hash.rs b/cmd/soroban-cli/src/commands/tx/hash.rs index d5b2c42e6..8d8ec6d82 100644 --- a/cmd/soroban-cli/src/commands/tx/hash.rs +++ b/cmd/soroban-cli/src/commands/tx/hash.rs @@ -1,6 +1,7 @@ -use crate::{commands::global, utils::transaction_hash}; use hex; +use crate::{commands::global, config::network, utils::transaction_hash}; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] @@ -8,7 +9,7 @@ pub enum Error { #[error(transparent)] XdrToBase64(#[from] soroban_env_host::xdr::Error), #[error(transparent)] - Config(#[from] super::super::network::Error), + Config(#[from] network::Error), } // Command to return the transaction hash submitted to a network @@ -17,7 +18,7 @@ pub enum Error { #[group(skip)] pub struct Cmd { #[clap(flatten)] - pub network: super::super::network::Args, + pub network: network::Args, } impl Cmd { diff --git a/cmd/soroban-cli/src/commands/config/alias.rs b/cmd/soroban-cli/src/config/alias.rs similarity index 100% rename from cmd/soroban-cli/src/commands/config/alias.rs rename to cmd/soroban-cli/src/config/alias.rs diff --git a/cmd/soroban-cli/src/commands/config/data.rs b/cmd/soroban-cli/src/config/data.rs similarity index 100% rename from cmd/soroban-cli/src/commands/config/data.rs rename to cmd/soroban-cli/src/config/data.rs diff --git a/cmd/soroban-cli/src/commands/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs similarity index 99% rename from cmd/soroban-cli/src/commands/config/locator.rs rename to cmd/soroban-cli/src/config/locator.rs index cbcb9e8b3..79c72f275 100644 --- a/cmd/soroban-cli/src/commands/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -63,7 +63,7 @@ pub enum Error { #[error(transparent)] String(#[from] std::string::FromUtf8Error), #[error(transparent)] - Secret(#[from] crate::commands::config::secret::Error), + Secret(#[from] crate::config::secret::Error), #[error(transparent)] Json(#[from] serde_json::Error), #[error("cannot access config dir for alias file")] diff --git a/cmd/soroban-cli/src/commands/config/mod.rs b/cmd/soroban-cli/src/config/mod.rs similarity index 97% rename from cmd/soroban-cli/src/commands/config/mod.rs rename to cmd/soroban-cli/src/config/mod.rs index bb55103c1..3632d7e31 100644 --- a/cmd/soroban-cli/src/commands/config/mod.rs +++ b/cmd/soroban-cli/src/config/mod.rs @@ -13,17 +13,14 @@ use crate::{ use self::{network::Network, secret::Secret}; -use super::{keys, network}; - pub mod alias; pub mod data; pub mod locator; +pub mod network; pub mod secret; #[derive(thiserror::Error, Debug)] pub enum Error { - #[error(transparent)] - Identity(#[from] keys::Error), #[error(transparent)] Network(#[from] network::Error), #[error(transparent)] diff --git a/cmd/soroban-cli/src/config/network.rs b/cmd/soroban-cli/src/config/network.rs new file mode 100644 index 000000000..ba63c016f --- /dev/null +++ b/cmd/soroban-cli/src/config/network.rs @@ -0,0 +1,200 @@ +use std::str::FromStr; + +use clap::arg; +use phf::phf_map; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use stellar_strkey::ed25519::PublicKey; + +use crate::{ + commands::HEADING_RPC, + rpc::{self, Client}, +}; + +use super::locator; +pub mod passphrase; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Config(#[from] locator::Error), + + #[error("network arg or rpc url and network passphrase are required if using the network")] + Network, + #[error(transparent)] + Http(#[from] http::Error), + #[error(transparent)] + Rpc(#[from] rpc::Error), + #[error(transparent)] + Hyper(#[from] hyper::Error), + #[error("Failed to parse JSON from {0}, {1}")] + FailedToParseJSON(String, serde_json::Error), + #[error("Invalid URL {0}")] + InvalidUrl(String), + #[error("Inproper response {0}")] + InproperResponse(String), + #[error("Currently not supported on windows. Please visit:\n{0}")] + WindowsNotSupported(String), +} + +#[derive(Debug, clap::Args, Clone, Default)] +#[group(skip)] +pub struct Args { + /// RPC server endpoint + #[arg( + long = "rpc-url", + requires = "network_passphrase", + required_unless_present = "network", + env = "STELLAR_RPC_URL", + help_heading = HEADING_RPC, + )] + pub rpc_url: Option, + /// Network passphrase to sign the transaction sent to the rpc server + #[arg( + long = "network-passphrase", + requires = "rpc_url", + required_unless_present = "network", + env = "STELLAR_NETWORK_PASSPHRASE", + help_heading = HEADING_RPC, + )] + pub network_passphrase: Option, + /// Name of network to use from config + #[arg( + long, + required_unless_present = "rpc_url", + env = "STELLAR_NETWORK", + help_heading = HEADING_RPC, + )] + pub network: Option, +} + +impl Args { + pub fn get(&self, locator: &locator::Args) -> Result { + if let Some(name) = self.network.as_deref() { + if let Ok(network) = locator.read_network(name) { + return Ok(network); + } + } + if let (Some(rpc_url), Some(network_passphrase)) = + (self.rpc_url.clone(), self.network_passphrase.clone()) + { + Ok(Network { + rpc_url, + network_passphrase, + }) + } else { + Err(Error::Network) + } + } +} + +#[derive(Debug, clap::Args, Serialize, Deserialize, Clone)] +#[group(skip)] +pub struct Network { + /// RPC server endpoint + #[arg( + long = "rpc-url", + env = "STELLAR_RPC_URL", + help_heading = HEADING_RPC, + )] + pub rpc_url: String, + /// Network passphrase to sign the transaction sent to the rpc server + #[arg( + long, + env = "STELLAR_NETWORK_PASSPHRASE", + help_heading = HEADING_RPC, + )] + pub network_passphrase: String, +} + +impl Network { + pub async fn helper_url(&self, addr: &str) -> Result { + use http::Uri; + tracing::debug!("address {addr:?}"); + let rpc_uri = Uri::from_str(&self.rpc_url) + .map_err(|_| Error::InvalidUrl(self.rpc_url.to_string()))?; + if self.network_passphrase.as_str() == passphrase::LOCAL { + let auth = rpc_uri.authority().unwrap().clone(); + let scheme = rpc_uri.scheme_str().unwrap(); + Ok(Uri::builder() + .authority(auth) + .scheme(scheme) + .path_and_query(format!("/friendbot?addr={addr}")) + .build()?) + } else { + let client = Client::new(&self.rpc_url)?; + let network = client.get_network().await?; + tracing::debug!("network {network:?}"); + let uri = client.friendbot_url().await?; + tracing::debug!("URI {uri:?}"); + Uri::from_str(&format!("{uri}?addr={addr}")).map_err(|e| { + tracing::error!("{e}"); + Error::InvalidUrl(uri.to_string()) + }) + } + } + + #[allow(clippy::similar_names)] + pub async fn fund_address(&self, addr: &PublicKey) -> Result<(), Error> { + let uri = self.helper_url(&addr.to_string()).await?; + tracing::debug!("URL {uri:?}"); + let response = match uri.scheme_str() { + Some("http") => hyper::Client::new().get(uri.clone()).await?, + Some("https") => { + let https = hyper_tls::HttpsConnector::new(); + hyper::Client::builder() + .build::<_, hyper::Body>(https) + .get(uri.clone()) + .await? + } + _ => { + return Err(Error::InvalidUrl(uri.to_string())); + } + }; + let body = hyper::body::to_bytes(response.into_body()).await?; + let res = serde_json::from_slice::(&body) + .map_err(|e| Error::FailedToParseJSON(uri.to_string(), e))?; + tracing::debug!("{res:#?}"); + if let Some(detail) = res.get("detail").and_then(Value::as_str) { + if detail.contains("createAccountAlreadyExist") { + eprintln!("Account already exists"); + } + } else if res.get("successful").is_none() { + return Err(Error::InproperResponse(res.to_string())); + } + Ok(()) + } + + pub fn rpc_uri(&self) -> Result { + http::Uri::from_str(&self.rpc_url).map_err(|_| Error::InvalidUrl(self.rpc_url.to_string())) + } +} + +pub static DEFAULTS: phf::Map<&'static str, (&'static str, &'static str)> = phf_map! { + "local" => ( + "http://localhost:8000/rpc", + passphrase::LOCAL, + ), + "futurenet" => ( + "https://rpc-futurenet.stellar.org:443", + passphrase::FUTURENET, + ), + "testnet" => ( + "https://soroban-testnet.stellar.org", + passphrase::TESTNET, + ), + "mainnet" => ( + "Bring Your Own: https://developers.stellar.org/docs/data/rpc/rpc-providers", + passphrase::MAINNET, + ), +}; + +impl From<&(&str, &str)> for Network { + /// Convert the return value of `DEFAULTS.get()` into a Network + fn from(n: &(&str, &str)) -> Self { + Self { + rpc_url: n.0.to_string(), + network_passphrase: n.1.to_string(), + } + } +} diff --git a/cmd/soroban-cli/src/config/network/passphrase.rs b/cmd/soroban-cli/src/config/network/passphrase.rs new file mode 100644 index 000000000..bdb534cdb --- /dev/null +++ b/cmd/soroban-cli/src/config/network/passphrase.rs @@ -0,0 +1,4 @@ +pub const LOCAL: &str = "Standalone Network ; February 2017"; +pub const TESTNET: &str = "Test SDF Network ; September 2015"; +pub const FUTURENET: &str = "Test SDF Future Network ; October 2022"; +pub const MAINNET: &str = "Public Global Stellar Network ; September 2015"; diff --git a/cmd/soroban-cli/src/commands/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs similarity index 100% rename from cmd/soroban-cli/src/commands/config/secret.rs rename to cmd/soroban-cli/src/config/secret.rs diff --git a/cmd/soroban-cli/src/get_spec.rs b/cmd/soroban-cli/src/get_spec.rs index e21722794..cd9477de2 100644 --- a/cmd/soroban-cli/src/get_spec.rs +++ b/cmd/soroban-cli/src/get_spec.rs @@ -7,9 +7,8 @@ use soroban_env_host::xdr::{ use soroban_spec::read::FromWasmError; pub use soroban_spec_tools::contract as contract_spec; -use crate::commands::config::{self, locator}; -use crate::commands::network; -use crate::commands::{config::data, global}; +use crate::commands::global; +use crate::config::{self, data, locator, network}; use crate::rpc; #[derive(thiserror::Error, Debug)] diff --git a/cmd/soroban-cli/src/lib.rs b/cmd/soroban-cli/src/lib.rs index f71ce55e2..0268a40e0 100644 --- a/cmd/soroban-cli/src/lib.rs +++ b/cmd/soroban-cli/src/lib.rs @@ -12,6 +12,7 @@ mod cli; pub use cli::main; pub mod commands; +pub mod config; pub mod fee; pub mod get_spec; pub mod key;