diff --git a/cmd/crates/soroban-test/src/lib.rs b/cmd/crates/soroban-test/src/lib.rs index 8ec628bf7..bda6ec420 100644 --- a/cmd/crates/soroban-test/src/lib.rs +++ b/cmd/crates/soroban-test/src/lib.rs @@ -30,7 +30,7 @@ use assert_fs::{fixture::FixtureError, prelude::PathChild, TempDir}; use fs_extra::dir::CopyOptions; use soroban_cli::{ - commands::{config, contract, contract::invoke, global}, + commands::{config, contract, contract::invoke, global, keys}, CommandParser, Pwd, }; @@ -82,6 +82,13 @@ impl TestEnv { pub fn new() -> Result { let this = TempDir::new().map(|temp_dir| TestEnv { temp_dir })?; std::env::set_var("XDG_CONFIG_HOME", this.temp_dir.as_os_str()); + this.new_assert_cmd("keys") + .arg("generate") + .arg("test") + .arg("-d") + .arg("--no-fund") + .assert(); + std::env::set_var("SOROBAN_ACCOUNT", "test"); Ok(this) } @@ -156,17 +163,17 @@ impl TestEnv { &self.temp_dir } - /// Returns the public key corresponding to the test identity's `hd_path` + /// Returns the public key corresponding to the test keys's `hd_path` pub fn test_address(&self, hd_path: usize) -> String { - self.cmd::(&format!("--hd-path={hd_path}")) + self.cmd::(&format!("--hd-path={hd_path}")) .public_key() .unwrap() .to_string() } - /// Returns the private key corresponding to the test identity's `hd_path` + /// Returns the private key corresponding to the test keys's `hd_path` pub fn test_show(&self, hd_path: usize) -> String { - self.cmd::(&format!("--hd-path={hd_path}")) + self.cmd::(&format!("--hd-path={hd_path}")) .private_key() .unwrap() .to_string() diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/src/test.rs b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/src/test.rs index 4f3845331..cf7929ef3 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/src/test.rs +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/src/test.rs @@ -27,10 +27,10 @@ fn test_atomic_swap() { let env = Env::default(); env.mock_all_auths(); - let a = Address::random(&env); - let b = Address::random(&env); + let a = Address::generate(&env); + let b = Address::generate(&env); - let token_admin = Address::random(&env); + let token_admin = Address::generate(&env); let (token_a, token_a_admin) = create_token_contract(&env, &token_admin); let (token_b, token_b_admin) = create_token_contract(&env, &token_admin); diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/src/test.rs b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/src/test.rs index 9aae46eba..dbdb17a33 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/src/test.rs +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/src/test.rs @@ -19,11 +19,11 @@ fn test() { let e = Env::default(); e.mock_all_auths(); - let admin1 = Address::random(&e); - let admin2 = Address::random(&e); - let user1 = Address::random(&e); - let user2 = Address::random(&e); - let user3 = Address::random(&e); + let admin1 = Address::generate(&e); + let admin2 = Address::generate(&e); + let user1 = Address::generate(&e); + let user2 = Address::generate(&e); + let user3 = Address::generate(&e); let token = create_token(&e, &admin1); token.mint(&user1, &1000); @@ -142,9 +142,9 @@ fn test_burn() { let e = Env::default(); e.mock_all_auths(); - let admin = Address::random(&e); - let user1 = Address::random(&e); - let user2 = Address::random(&e); + let admin = Address::generate(&e); + let user1 = Address::generate(&e); + let user2 = Address::generate(&e); let token = create_token(&e, &admin); token.mint(&user1, &1000); @@ -199,9 +199,9 @@ fn transfer_insufficient_balance() { let e = Env::default(); e.mock_all_auths(); - let admin = Address::random(&e); - let user1 = Address::random(&e); - let user2 = Address::random(&e); + let admin = Address::generate(&e); + let user1 = Address::generate(&e); + let user2 = Address::generate(&e); let token = create_token(&e, &admin); token.mint(&user1, &1000); @@ -216,10 +216,10 @@ fn transfer_from_insufficient_allowance() { let e = Env::default(); e.mock_all_auths(); - let admin = Address::random(&e); - let user1 = Address::random(&e); - let user2 = Address::random(&e); - let user3 = Address::random(&e); + let admin = Address::generate(&e); + let user1 = Address::generate(&e); + let user2 = Address::generate(&e); + let user3 = Address::generate(&e); let token = create_token(&e, &admin); token.mint(&user1, &1000); @@ -235,7 +235,7 @@ fn transfer_from_insufficient_allowance() { #[should_panic(expected = "already initialized")] fn initialize_already_initialized() { let e = Env::default(); - let admin = Address::random(&e); + let admin = Address::generate(&e); let token = create_token(&e, &admin); token.initialize(&admin, &10, &"name".into_val(&e), &"symbol".into_val(&e)); @@ -245,7 +245,7 @@ fn initialize_already_initialized() { #[should_panic(expected = "Decimal must fit in a u8")] fn decimal_is_over_max() { let e = Env::default(); - let admin = Address::random(&e); + let admin = Address::generate(&e); let token = TokenClient::new(&e, &e.register_contract(None, Token {})); token.initialize( &admin, diff --git a/cmd/crates/soroban-test/tests/it/config.rs b/cmd/crates/soroban-test/tests/it/config.rs index a0a240af1..5912b2cf5 100644 --- a/cmd/crates/soroban-test/tests/it/config.rs +++ b/cmd/crates/soroban-test/tests/it/config.rs @@ -2,8 +2,8 @@ use assert_fs::TempDir; use soroban_test::TestEnv; use std::{fs, path::Path}; -use crate::util::{add_identity, add_test_id, SecretKind, DEFAULT_SEED_PHRASE}; -use soroban_cli::commands::config::network; +use crate::util::{add_key, add_test_id, SecretKind, DEFAULT_SEED_PHRASE}; +use soroban_cli::commands::network; const NETWORK_PASSPHRASE: &str = "Local Sandbox Stellar Network ; September 2022"; @@ -32,8 +32,7 @@ fn set_and_remove_network() { // .assert() // .stdout(""); sandbox - .new_assert_cmd("config") - .arg("network") + .new_assert_cmd("network") .arg("ls") .assert() .stdout("\n"); @@ -42,8 +41,7 @@ fn set_and_remove_network() { fn add_network(sandbox: &TestEnv, name: &str) { sandbox - .new_assert_cmd("config") - .arg("network") + .new_assert_cmd("network") .arg("add") .args([ "--rpc-url=https://127.0.0.1", @@ -59,9 +57,8 @@ fn add_network(sandbox: &TestEnv, name: &str) { fn add_network_global(sandbox: &TestEnv, dir: &Path, name: &str) { sandbox - .new_assert_cmd("config") + .new_assert_cmd("network") .env("XDG_CONFIG_HOME", dir.to_str().unwrap()) - .arg("network") .arg("add") .arg("--global") .arg("--rpc-url") @@ -81,18 +78,16 @@ fn set_and_remove_global_network() { add_network_global(&sandbox, &dir, "global"); sandbox - .new_assert_cmd("config") + .new_assert_cmd("network") .env("XDG_CONFIG_HOME", dir.to_str().unwrap()) - .arg("network") .arg("ls") .arg("--global") .assert() .stdout("global\n"); sandbox - .new_assert_cmd("config") + .new_assert_cmd("network") .env("XDG_CONFIG_HOME", dir.to_str().unwrap()) - .arg("network") .arg("rm") .arg("--global") .arg("global") @@ -100,9 +95,8 @@ fn set_and_remove_global_network() { .stdout(""); sandbox - .new_assert_cmd("config") + .new_assert_cmd("network") .env("XDG_CONFIG_HOME", dir.to_str().unwrap()) - .arg("network") .arg("ls") .assert() .stdout("\n"); @@ -143,42 +137,41 @@ fn multiple_networks() { } #[test] -fn read_identity() { +fn read_key() { let sandbox = TestEnv::default(); let dir = sandbox.dir().as_ref(); add_test_id(dir); let ident_dir = dir.join(".soroban/identity"); assert!(ident_dir.exists()); sandbox - .new_assert_cmd("config") - .arg("identity") + .new_assert_cmd("keys") .arg("ls") .assert() - .stdout("test_id\n"); + .stdout(predicates::str::contains("test_id\n")); } #[test] -fn generate_identity() { +fn generate_key() { let sandbox = TestEnv::default(); sandbox - .new_assert_cmd("config") - .arg("identity") + .new_assert_cmd("keys") .arg("generate") + .arg("--network=futurenet") + .arg("--no-fund") .arg("--seed") .arg("0000000000000000") - .arg("test") + .arg("test_2") .assert() .stdout("") .success(); sandbox - .new_assert_cmd("config") - .arg("identity") + .new_assert_cmd("keys") .arg("ls") .assert() - .stdout("test\n"); + .stdout(predicates::str::contains("test_2\n")); let file_contents = - fs::read_to_string(sandbox.dir().join(".soroban/identity/test.toml")).unwrap(); + fs::read_to_string(sandbox.dir().join(".soroban/identity/test_2.toml")).unwrap(); assert_eq!( file_contents, format!("seed_phrase = \"{DEFAULT_SEED_PHRASE}\"\n") @@ -189,7 +182,7 @@ fn generate_identity() { fn seed_phrase() { let sandbox = TestEnv::default(); let dir = sandbox.dir(); - add_identity( + add_key( dir, "test_seed", SecretKind::Seed, @@ -197,20 +190,11 @@ fn seed_phrase() { ); sandbox - .new_assert_cmd("config") + .new_assert_cmd("keys") .current_dir(dir) - .arg("identity") .arg("ls") .assert() - .stdout("test_seed\n"); -} - -#[test] -fn read_address() { - let sandbox = TestEnv::default(); - for hd_path in 0..2 { - test_hd_path(&sandbox, hd_path); - } + .stdout(predicates::str::contains("test_seed\n")); } #[test] @@ -218,12 +202,11 @@ fn use_env() { let sandbox = TestEnv::default(); sandbox - .new_assert_cmd("config") + .new_assert_cmd("keys") .env( "SOROBAN_SECRET_KEY", "SDIY6AQQ75WMD4W46EYB7O6UYMHOCGQHLAQGQTKHDX4J2DYQCHVCQYFD", ) - .arg("identity") .arg("add") .arg("bob") .assert() @@ -231,19 +214,10 @@ fn use_env() { .success(); sandbox - .new_assert_cmd("config") - .arg("identity") + .new_assert_cmd("keys") .arg("show") .arg("bob") .assert() .success() .stdout("SDIY6AQQ75WMD4W46EYB7O6UYMHOCGQHLAQGQTKHDX4J2DYQCHVCQYFD\n"); } - -fn test_hd_path(sandbox: &TestEnv, hd_path: usize) { - let seed_phrase = sep5::SeedPhrase::from_seed_phrase(DEFAULT_SEED_PHRASE).unwrap(); - let key_pair = seed_phrase.from_path_index(hd_path, None).unwrap(); - let pub_key = key_pair.public().to_string(); - let test_address = sandbox.test_address(hd_path); - assert_eq!(pub_key, test_address); -} diff --git a/cmd/crates/soroban-test/tests/it/hello_world.rs b/cmd/crates/soroban-test/tests/it/hello_world.rs index 38b78ee38..4c45403a1 100644 --- a/cmd/crates/soroban-test/tests/it/hello_world.rs +++ b/cmd/crates/soroban-test/tests/it/hello_world.rs @@ -1,7 +1,4 @@ -use soroban_cli::commands::{ - config::identity, - contract::{self, fetch}, -}; +use soroban_cli::commands::contract::{self, fetch}; use soroban_test::TestEnv; use std::path::PathBuf; @@ -11,13 +8,6 @@ use crate::util::{ TEST_SALT, }; - - - - - - - #[tokio::test] async fn fetch() { if !is_rpc() { diff --git a/cmd/crates/soroban-test/tests/it/integration/custom_types.rs b/cmd/crates/soroban-test/tests/it/integration/custom_types.rs index 4e36b452c..fda2c1f61 100644 --- a/cmd/crates/soroban-test/tests/it/integration/custom_types.rs +++ b/cmd/crates/soroban-test/tests/it/integration/custom_types.rs @@ -341,8 +341,8 @@ fn boolean(sandbox: &TestEnv, id: &str) { .assert() .success() .stdout( - r#"true -"#, + r"true +", ); } fn boolean_two(sandbox: &TestEnv, id: &str) { @@ -352,8 +352,8 @@ fn boolean_two(sandbox: &TestEnv, id: &str) { .assert() .success() .stdout( - r#"true -"#, + r"true +", ); } @@ -362,8 +362,8 @@ fn boolean_no_flag(sandbox: &TestEnv, id: &str) { .assert() .success() .stdout( - r#"false -"#, + r"false +", ); } @@ -374,8 +374,8 @@ fn boolean_false(sandbox: &TestEnv, id: &str) { .assert() .success() .stdout( - r#"false -"#, + r"false +", ); } @@ -385,15 +385,15 @@ fn boolean_not(sandbox: &TestEnv, id: &str) { .assert() .success() .stdout( - r#"false -"#, + r"false +", ); } fn boolean_not_no_flag(sandbox: &TestEnv, id: &str) { invoke_custom(sandbox, id, "not").assert().success().stdout( - r#"true -"#, + r"true +", ); } @@ -402,8 +402,8 @@ fn option_none(sandbox: &TestEnv, id: &str) { .assert() .success() .stdout( - r#"null -"#, + r"null +", ); } @@ -413,7 +413,7 @@ fn option_some(sandbox: &TestEnv, id: &str) { .assert() .success() .stdout( - r#"1 -"#, + r"1 +", ); } 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 fed4f4493..7714f70dd 100644 --- a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs +++ b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs @@ -1,6 +1,6 @@ use soroban_cli::commands::{ - config::identity, contract::{self, fetch}, + keys, }; use soroban_test::TestEnv; @@ -111,7 +111,7 @@ fn invoke_auth(sandbox: &TestEnv, id: &str) { async fn invoke_auth_with_identity(sandbox: &TestEnv, id: &str) { sandbox - .cmd::("test -d ") + .cmd::("test -d ") .run() .await .unwrap(); diff --git a/cmd/crates/soroban-test/tests/it/integration/util.rs b/cmd/crates/soroban-test/tests/it/integration/util.rs index 4cc41474f..ea27680b7 100644 --- a/cmd/crates/soroban-test/tests/it/integration/util.rs +++ b/cmd/crates/soroban-test/tests/it/integration/util.rs @@ -2,14 +2,14 @@ use soroban_cli::commands::contract; use soroban_test::{TestEnv, Wasm}; use std::{fmt::Display, path::Path}; -use crate::util::{add_identity, SecretKind}; +use crate::util::{add_key, SecretKind}; pub const HELLO_WORLD: &Wasm = &Wasm::Custom("test-wasms", "test_hello_world"); pub const CUSTOM_TYPES: &Wasm = &Wasm::Custom("test-wasms", "test_custom_types"); pub fn add_test_seed(dir: &Path) -> String { let name = "test_seed"; - add_identity( + add_key( dir, name, SecretKind::Seed, diff --git a/cmd/crates/soroban-test/tests/it/integration/wrap.rs b/cmd/crates/soroban-test/tests/it/integration/wrap.rs index f1a453e7a..a69e70c7c 100644 --- a/cmd/crates/soroban-test/tests/it/integration/wrap.rs +++ b/cmd/crates/soroban-test/tests/it/integration/wrap.rs @@ -1,9 +1,6 @@ use soroban_cli::CommandParser; use soroban_cli::{ - commands::{ - config::{self}, - lab::token::wrap, - }, + commands::{contract::deploy::asset, keys}, utils::contract_id_hash_from_asset, }; use soroban_test::TestEnv; @@ -14,14 +11,16 @@ use super::util::network_passphrase; #[ignore] async fn burn() { let sandbox = &TestEnv::default(); - let address = config::identity::address::Cmd::parse("--hd-path=0") + let network_passphrase = network_passphrase().unwrap(); + println!("NETWORK_PASSPHRASE: {network_passphrase:?}"); + let address = keys::address::Cmd::parse("test") .unwrap() .public_key() .unwrap(); let asset = format!("native:{address}"); wrap_cmd(&asset).run().await.unwrap(); let asset = soroban_cli::utils::parsing::parse_asset(&asset).unwrap(); - let hash = contract_id_hash_from_asset(&asset, &network_passphrase().unwrap()).unwrap(); + let hash = contract_id_hash_from_asset(&asset, &network_passphrase).unwrap(); let id = stellar_strkey::Contract(hash.0).to_string(); assert_eq!( "CAMTHSPKXZJIRTUXQP5QWJIFH3XIDMKLFAWVQOFOXPTKAW5GKV37ZC4N", @@ -33,6 +32,7 @@ async fn burn() { .invoke(&[ "--id", &id, + "--source=test", "--", "authorized", "--id", @@ -44,7 +44,16 @@ async fn burn() { assert_eq!( "\"9223372036854775807\"", sandbox - .invoke(&["--id", &id, "--", "balance", "--id", &address.to_string()]) + .invoke(&[ + "--id", + &id, + "--source", + "test", + "--", + "balance", + "--id", + &address.to_string() + ]) .await .unwrap(), ); @@ -55,6 +64,7 @@ async fn burn() { .invoke(&[ "--id", &id, + "--source=test", "--", "burn", "--id", @@ -68,12 +78,20 @@ async fn burn() { assert_eq!( "\"9223372036854775707\"", sandbox - .invoke(&["--id", &id, "--", "balance", "--id", &address.to_string()]) + .invoke(&[ + "--id", + &id, + "--source=test", + "--", + "balance", + "--id", + &address.to_string() + ]) .await .unwrap(), ); } -fn wrap_cmd(asset: &str) -> wrap::Cmd { - wrap::Cmd::parse_arg_vec(&[&format!("--asset={asset}")]).unwrap() +fn wrap_cmd(asset: &str) -> asset::Cmd { + asset::Cmd::parse_arg_vec(&["--source=test", &format!("--asset={asset}")]).unwrap() } diff --git a/cmd/crates/soroban-test/tests/it/lab.rs b/cmd/crates/soroban-test/tests/it/lab.rs deleted file mode 100644 index 85d8dc650..000000000 --- a/cmd/crates/soroban-test/tests/it/lab.rs +++ /dev/null @@ -1,27 +0,0 @@ -use soroban_test::TestEnv; -use std::path::PathBuf; - -#[test] -#[cfg_attr(target_os = "windows", ignore)] -fn lab_xdr_decode() { - let sandbox = TestEnv::default(); - let cargo_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let ref_xdr_filename = cargo_dir.join("tests/it/lab_test_transaction_envelope.txt"); - let ref_xdr = std::fs::read_to_string(ref_xdr_filename.clone()).unwrap(); - - let cmd = sandbox - .new_assert_cmd("lab") - .arg("xdr") - .arg("dec") - .arg("--type") - .arg("TransactionEnvelope") - .arg("--xdr") - .arg("AAAAAgAAAABzdv3ojkzWHMD7KUoXhrPx0GH18vHKV0ZfqpMiEblG1gAAAGQAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAADRjwIQ/2zB8tzxMB+71MMO4RoHWCBoTUcd+J0PEBHqKAAAAOjUpRAAAAAAAAAAAAERuUbWAAAAQKAEpum2TGh/P2K0/eOxeXw1eGEG5fl/Ft2a/j7YUN+H3XNjkFAfYnJvfpmvTsNYqPsoHKufgRpDmJuAhd0xJgk=") - .assert() - .success(); - let stdout = String::from_utf8(cmd.get_output().clone().stdout).unwrap(); - if ref_xdr.is_empty() { - std::fs::write(ref_xdr_filename, stdout.clone()).unwrap(); - } - assert_eq!(stdout, ref_xdr); -} diff --git a/cmd/crates/soroban-test/tests/it/main.rs b/cmd/crates/soroban-test/tests/it/main.rs index 3077d2fa0..a6b18cb22 100644 --- a/cmd/crates/soroban-test/tests/it/main.rs +++ b/cmd/crates/soroban-test/tests/it/main.rs @@ -3,7 +3,6 @@ mod config; mod help; #[cfg(feature = "integration")] mod integration; -mod lab; mod plugin; mod util; mod version; diff --git a/cmd/crates/soroban-test/tests/it/util.rs b/cmd/crates/soroban-test/tests/it/util.rs index ad5dacc7d..6d6251012 100644 --- a/cmd/crates/soroban-test/tests/it/util.rs +++ b/cmd/crates/soroban-test/tests/it/util.rs @@ -15,7 +15,7 @@ pub enum SecretKind { } #[allow(clippy::needless_pass_by_value)] -pub fn add_identity(dir: &Path, name: &str, kind: SecretKind, data: &str) { +pub fn add_key(dir: &Path, name: &str, kind: SecretKind, data: &str) { let secret = match kind { SecretKind::Seed => Secret::SeedPhrase { seed_phrase: data.to_string(), @@ -32,7 +32,7 @@ pub fn add_identity(dir: &Path, name: &str, kind: SecretKind, data: &str) { pub fn add_test_id(dir: &Path) -> String { let name = "test_id"; - add_identity( + add_key( dir, name, SecretKind::Key, @@ -52,7 +52,17 @@ pub async fn invoke_custom( arg: &str, wasm: &Path, ) -> Result { - let mut i: contract::invoke::Cmd = sandbox.cmd_arr(&["--id", id, "--", func, arg]); + let mut i: contract::invoke::Cmd = sandbox.cmd_arr(&[ + "--id", + id, + "--network", + "futurenet", + "--source", + "default", + "--", + func, + arg, + ]); i.wasm = Some(wasm.to_path_buf()); i.config.network.network = Some("futurenet".to_owned()); i.invoke(&soroban_cli::commands::global::Args::default()) diff --git a/cmd/soroban-cli/src/commands/config/identity/ls.rs b/cmd/soroban-cli/src/commands/config/identity/ls.rs deleted file mode 100644 index 0b866e0ec..000000000 --- a/cmd/soroban-cli/src/commands/config/identity/ls.rs +++ /dev/null @@ -1,22 +0,0 @@ -use super::super::locator; -use clap::command; - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error(transparent)] - Config(#[from] locator::Error), -} - -#[derive(Debug, clap::Parser, Clone)] -#[group(skip)] -pub struct Cmd { - #[command(flatten)] - pub config_locator: locator::Args, -} - -impl Cmd { - pub fn run(&self) -> Result<(), Error> { - println!("{}", self.config_locator.list_identities()?.join("\n")); - Ok(()) - } -} diff --git a/cmd/soroban-cli/src/commands/config/locator.rs b/cmd/soroban-cli/src/commands/config/locator.rs index 2c174a9b2..2688b043f 100644 --- a/cmd/soroban-cli/src/commands/config/locator.rs +++ b/cmd/soroban-cli/src/commands/config/locator.rs @@ -58,6 +58,8 @@ pub enum Error { ConfigMissing(String, String), #[error(transparent)] String(#[from] std::string::FromUtf8Error), + #[error(transparent)] + Secret(#[from] crate::commands::config::secret::Error), } #[derive(Debug, clap::Args, Default, Clone)] @@ -67,6 +69,7 @@ pub struct Args { #[arg(long)] pub global: bool, + /// Location of config directory, default is "." #[arg(long, help_heading = "TESTING_OPTIONS")] pub config_dir: Option, } @@ -152,6 +155,20 @@ impl Args { .collect()) } + pub fn list_identities_long(&self) -> Result, Error> { + Ok(KeyType::Identity + .list_paths(&self.local_and_global()?) + .into_iter() + .flatten() + .map(|(name, location)| { + let path = match location { + Location::Local(path) | Location::Global(path) => path, + }; + (name, format!("{}", path.display())) + }) + .collect()) + } + pub fn list_networks(&self) -> Result, Error> { Ok(KeyType::Network .list_paths(&self.local_and_global()?) diff --git a/cmd/soroban-cli/src/commands/config/mod.rs b/cmd/soroban-cli/src/commands/config/mod.rs index f4d8ec554..be76e77f9 100644 --- a/cmd/soroban-cli/src/commands/config/mod.rs +++ b/cmd/soroban-cli/src/commands/config/mod.rs @@ -7,25 +7,25 @@ use crate::Pwd; use self::{network::Network, secret::Secret}; -pub mod identity; +use super::{keys, network}; + pub mod locator; -pub mod network; pub mod secret; #[derive(Debug, Parser)] pub enum Cmd { - /// Configure different identities to sign transactions. - #[command(subcommand)] - Identity(identity::Cmd), - /// Configure different networks + /// Configure different networks. Depraecated, use `soroban network` instead. #[command(subcommand)] Network(network::Cmd), + /// Identity management. Deprecated, use `soroban keys` instead. + #[command(subcommand)] + Identity(keys::Cmd), } #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] - Identity(#[from] identity::Error), + Identity(#[from] keys::Error), #[error(transparent)] Network(#[from] network::Error), #[error(transparent)] @@ -52,7 +52,7 @@ pub struct Args { #[arg(long, visible_alias = "source", env = "SOROBAN_ACCOUNT")] /// Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` - pub source_account: Option, + pub source_account: String, #[arg(long)] /// If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` @@ -64,12 +64,7 @@ pub struct Args { impl Args { pub fn key_pair(&self) -> Result { - let key = if let Some(source_account) = &self.source_account { - self.account(source_account)? - } else { - secret::Secret::test_seed_phrase()? - }; - + let key = self.account(&self.source_account)?; Ok(key.key_pair(self.hd_path)?) } diff --git a/cmd/soroban-cli/src/commands/config/secret.rs b/cmd/soroban-cli/src/commands/config/secret.rs index 7e6f08a90..4684e2a88 100644 --- a/cmd/soroban-cli/src/commands/config/secret.rs +++ b/cmd/soroban-cli/src/commands/config/secret.rs @@ -92,6 +92,14 @@ impl FromStr for Secret { } } +impl From for Secret { + fn from(value: PrivateKey) -> Self { + Secret::SecretKey { + secret_key: value.to_string(), + } + } +} + impl Secret { pub fn private_key(&self, index: Option) -> Result { Ok(match self { diff --git a/cmd/soroban-cli/src/commands/contract/asset.rs b/cmd/soroban-cli/src/commands/contract/asset.rs new file mode 100644 index 000000000..ad7be0207 --- /dev/null +++ b/cmd/soroban-cli/src/commands/contract/asset.rs @@ -0,0 +1,27 @@ +use super::{deploy, id}; + +#[derive(Debug, clap::Subcommand)] +pub enum Cmd { + /// Get Id of builtin Soroban Asset Contract. Deprecated, use `soroban contract id asset` instead + Id(id::asset::Cmd), + /// Deploy builtin Soroban Asset Contract + Deploy(deploy::asset::Cmd), +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Id(#[from] id::asset::Error), + #[error(transparent)] + Deploy(#[from] deploy::asset::Error), +} + +impl Cmd { + pub async fn run(&self) -> Result<(), Error> { + match &self { + Cmd::Id(id) => id.run()?, + Cmd::Deploy(asset) => asset.run().await?, + } + Ok(()) + } +} diff --git a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs index 1c39cf2ae..19c7eecd6 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs @@ -6,11 +6,9 @@ use soroban_spec_typescript::{self as typescript, boilerplate::Project}; use crate::wasm; use crate::{ commands::{ - config::{ - locator, - network::{self, Network}, - }, + config::locator, contract::{self, fetch}, + network::{self, Network}, }, utils::contract_spec::{self, ContractSpec}, }; diff --git a/cmd/soroban-cli/src/commands/contract/deploy.rs b/cmd/soroban-cli/src/commands/contract/deploy.rs index c89654a4d..9baf44590 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy.rs @@ -1,241 +1,28 @@ -use std::array::TryFromSliceError; -use std::fmt::Debug; -use std::num::ParseIntError; - -use clap::{arg, command, Parser}; -use rand::Rng; -use sha2::{Digest, Sha256}; -use soroban_env_host::xdr::Limits; -use soroban_env_host::{ - xdr::{ - AccountId, ContractExecutable, ContractIdPreimage, ContractIdPreimageFromAddress, - CreateContractArgs, Error as XdrError, Hash, HashIdPreimage, HashIdPreimageContractId, - HostFunction, InvokeHostFunctionOp, Memo, MuxedAccount, Operation, OperationBody, - Preconditions, PublicKey, ScAddress, SequenceNumber, Transaction, TransactionExt, Uint256, - VecM, WriteXdr, - }, - HostError, -}; - -use crate::{ - commands::{config, contract::install, HEADING_RPC}, - rpc::{self, Client}, - utils, wasm, -}; - -#[derive(Parser, Debug, Clone)] -#[command(group( - clap::ArgGroup::new("wasm_src") - .required(true) - .args(&["wasm", "wasm_hash"]), -))] -#[group(skip)] -pub struct Cmd { - /// WASM file to deploy - #[arg(long, group = "wasm_src")] - wasm: Option, - /// Hash of the already installed/deployed WASM file - #[arg(long = "wasm-hash", conflicts_with = "wasm", group = "wasm_src")] - wasm_hash: Option, - /// Custom salt 32-byte salt for the token id - #[arg( - long, - help_heading = HEADING_RPC, - )] - salt: Option, - #[command(flatten)] - config: config::Args, - #[command(flatten)] - pub fee: crate::fee::Args, - #[arg(long, short = 'i', default_value = "false")] - /// Whether to ignore safety checks when deploying contracts - pub ignore_checks: bool, +pub mod asset; +pub mod wasm; + +#[derive(Debug, clap::Subcommand)] +pub enum Cmd { + /// Deploy builtin Soroban Asset Contract + Asset(asset::Cmd), + /// Deploy normal Wasm Contract + Wasm(wasm::Cmd), } #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] - Install(#[from] install::Error), - #[error(transparent)] - Host(#[from] HostError), - #[error("error parsing int: {0}")] - ParseIntError(#[from] ParseIntError), - #[error("internal conversion error: {0}")] - TryFromSliceError(#[from] TryFromSliceError), - #[error("xdr processing error: {0}")] - Xdr(#[from] XdrError), - #[error("jsonrpc error: {0}")] - JsonRpc(#[from] jsonrpsee_core::Error), - #[error("cannot parse salt: {salt}")] - CannotParseSalt { salt: String }, - #[error("cannot parse contract ID {contract_id}: {error}")] - CannotParseContractId { - contract_id: String, - error: stellar_strkey::DecodeError, - }, - #[error("cannot parse WASM hash {wasm_hash}: {error}")] - CannotParseWasmHash { - wasm_hash: String, - error: stellar_strkey::DecodeError, - }, - #[error("Must provide either --wasm or --wash-hash")] - WasmNotProvided, - #[error(transparent)] - Rpc(#[from] rpc::Error), - #[error(transparent)] - Config(#[from] config::Error), - #[error(transparent)] - StrKey(#[from] stellar_strkey::DecodeError), + Asset(#[from] asset::Error), #[error(transparent)] - Infallible(#[from] std::convert::Infallible), + Wasm(#[from] wasm::Error), } impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let res_str = self.run_and_get_contract_id().await?; - println!("{res_str}"); + match &self { + Cmd::Asset(asset) => asset.run().await?, + Cmd::Wasm(wasm) => wasm.run().await?, + } Ok(()) } - - pub async fn run_and_get_contract_id(&self) -> Result { - let wasm_hash = if let Some(wasm) = &self.wasm { - let hash = install::Cmd { - wasm: wasm::Args { wasm: wasm.clone() }, - config: self.config.clone(), - fee: self.fee.clone(), - ignore_checks: self.ignore_checks, - } - .run_and_get_hash() - .await?; - hex::encode(hash) - } else { - self.wasm_hash - .as_ref() - .ok_or(Error::WasmNotProvided)? - .to_string() - }; - - let hash = Hash(utils::contract_id_from_str(&wasm_hash).map_err(|e| { - Error::CannotParseWasmHash { - wasm_hash: wasm_hash.clone(), - error: e, - } - })?); - - self.run_against_rpc_server(hash).await - } - - async fn run_against_rpc_server(&self, wasm_hash: Hash) -> Result { - let network = self.config.get_network()?; - let salt: [u8; 32] = match &self.salt { - Some(h) => soroban_spec_tools::utils::padded_hex_from_str(h, 32) - .map_err(|_| Error::CannotParseSalt { salt: h.clone() })? - .try_into() - .map_err(|_| Error::CannotParseSalt { salt: h.clone() })?, - None => rand::thread_rng().gen::<[u8; 32]>(), - }; - - let client = Client::new(&network.rpc_url)?; - client - .verify_network_passphrase(Some(&network.network_passphrase)) - .await?; - let key = self.config.key_pair()?; - - // Get the account sequence number - let public_strkey = - stellar_strkey::ed25519::PublicKey(key.verifying_key().to_bytes()).to_string(); - - let account_details = client.get_account(&public_strkey).await?; - let sequence: i64 = account_details.seq_num.into(); - let (tx, contract_id) = build_create_contract_tx( - wasm_hash, - sequence + 1, - self.fee.fee, - &network.network_passphrase, - salt, - &key, - )?; - client - .prepare_and_send_transaction(&tx, &key, &[], &network.network_passphrase, None, None) - .await?; - Ok(stellar_strkey::Contract(contract_id.0).to_string()) - } -} - -fn build_create_contract_tx( - hash: Hash, - sequence: i64, - fee: u32, - network_passphrase: &str, - salt: [u8; 32], - key: &ed25519_dalek::SigningKey, -) -> Result<(Transaction, Hash), Error> { - let source_account = AccountId(PublicKey::PublicKeyTypeEd25519( - key.verifying_key().to_bytes().into(), - )); - - let contract_id_preimage = ContractIdPreimage::Address(ContractIdPreimageFromAddress { - address: ScAddress::Account(source_account), - salt: Uint256(salt), - }); - let contract_id = get_contract_id(contract_id_preimage.clone(), network_passphrase)?; - - let op = Operation { - source_account: None, - body: OperationBody::InvokeHostFunction(InvokeHostFunctionOp { - host_function: HostFunction::CreateContract(CreateContractArgs { - contract_id_preimage, - executable: ContractExecutable::Wasm(hash), - }), - auth: VecM::default(), - }), - }; - let tx = Transaction { - source_account: MuxedAccount::Ed25519(Uint256(key.verifying_key().to_bytes())), - fee, - seq_num: SequenceNumber(sequence), - cond: Preconditions::None, - memo: Memo::None, - operations: vec![op].try_into()?, - ext: TransactionExt::V0, - }; - - Ok((tx, Hash(contract_id.into()))) -} - -fn get_contract_id( - contract_id_preimage: ContractIdPreimage, - network_passphrase: &str, -) -> Result { - let network_id = Hash(Sha256::digest(network_passphrase.as_bytes()).into()); - let preimage = HashIdPreimage::ContractId(HashIdPreimageContractId { - network_id, - contract_id_preimage, - }); - let preimage_xdr = preimage.to_xdr(Limits::none())?; - Ok(Hash(Sha256::digest(preimage_xdr).into())) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_build_create_contract() { - let hash = hex::decode("0000000000000000000000000000000000000000000000000000000000000000") - .unwrap() - .try_into() - .unwrap(); - let result = build_create_contract_tx( - Hash(hash), - 300, - 1, - "Public Global Stellar Network ; September 2015", - [0u8; 32], - &utils::parse_secret_key("SBFGFF27Y64ZUGFAIG5AMJGQODZZKV2YQKAVUUN4HNE24XZXD2OEUVUP") - .unwrap(), - ); - - assert!(result.is_ok()); - } } diff --git a/cmd/soroban-cli/src/commands/lab/token/wrap.rs b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs similarity index 92% rename from cmd/soroban-cli/src/commands/lab/token/wrap.rs rename to cmd/soroban-cli/src/commands/contract/deploy/asset.rs index 2b6f4dd4f..c10bf8164 100644 --- a/cmd/soroban-cli/src/commands/lab/token/wrap.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs @@ -99,21 +99,6 @@ impl Cmd { } } -/// # Errors -/// -/// Might return an error -pub fn vec_to_hash(res: &ScVal) -> Result { - if let ScVal::Address(ScAddress::Contract(res_contract)) = &res { - let mut hash_bytes: [u8; 32] = [0; 32]; - for (i, b) in res_contract.0.iter().enumerate() { - hash_bytes[i] = *b; - } - Ok(Hash(hash_bytes)) - } else { - Err(XdrError::Invalid) - } -} - fn build_wrap_token_tx( asset: &Asset, contract_id: &Hash, diff --git a/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs new file mode 100644 index 000000000..76c130173 --- /dev/null +++ b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs @@ -0,0 +1,228 @@ +use std::array::TryFromSliceError; +use std::fmt::Debug; +use std::num::ParseIntError; + +use clap::{arg, command, Parser}; +use rand::Rng; +use soroban_env_host::{ + xdr::{ + AccountId, ContractExecutable, ContractIdPreimage, ContractIdPreimageFromAddress, + CreateContractArgs, Error as XdrError, Hash, HostFunction, InvokeHostFunctionOp, Memo, + MuxedAccount, Operation, OperationBody, Preconditions, PublicKey, ScAddress, + SequenceNumber, Transaction, TransactionExt, Uint256, VecM, + }, + HostError, +}; + +use crate::commands::contract::{self, id::wasm::get_contract_id}; +use crate::{ + commands::{config, contract::install, HEADING_RPC}, + rpc::{self, Client}, + utils, wasm, +}; + +#[derive(Parser, Debug, Clone)] +#[command(group( + clap::ArgGroup::new("wasm_src") + .required(true) + .args(&["wasm", "wasm_hash"]), +))] +#[group(skip)] +pub struct Cmd { + /// WASM file to deploy + #[arg(long, group = "wasm_src")] + wasm: Option, + /// Hash of the already installed/deployed WASM file + #[arg(long = "wasm-hash", conflicts_with = "wasm", group = "wasm_src")] + wasm_hash: Option, + /// Custom salt 32-byte salt for the token id + #[arg( + long, + help_heading = HEADING_RPC, + )] + salt: Option, + #[command(flatten)] + config: config::Args, + #[command(flatten)] + pub fee: crate::fee::Args, + #[arg(long, short = 'i', default_value = "false")] + /// Whether to ignore safety checks when deploying contracts + pub ignore_checks: bool, +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Install(#[from] install::Error), + #[error(transparent)] + Host(#[from] HostError), + #[error("error parsing int: {0}")] + ParseIntError(#[from] ParseIntError), + #[error("internal conversion error: {0}")] + TryFromSliceError(#[from] TryFromSliceError), + #[error("xdr processing error: {0}")] + Xdr(#[from] XdrError), + #[error("jsonrpc error: {0}")] + JsonRpc(#[from] jsonrpsee_core::Error), + #[error("cannot parse salt: {salt}")] + CannotParseSalt { salt: String }, + #[error("cannot parse contract ID {contract_id}: {error}")] + CannotParseContractId { + contract_id: String, + error: stellar_strkey::DecodeError, + }, + #[error("cannot parse WASM hash {wasm_hash}: {error}")] + CannotParseWasmHash { + wasm_hash: String, + error: stellar_strkey::DecodeError, + }, + #[error("Must provide either --wasm or --wash-hash")] + WasmNotProvided, + #[error(transparent)] + Rpc(#[from] rpc::Error), + #[error(transparent)] + Config(#[from] config::Error), + #[error(transparent)] + StrKey(#[from] stellar_strkey::DecodeError), + #[error(transparent)] + Infallible(#[from] std::convert::Infallible), + #[error(transparent)] + WasmId(#[from] contract::id::wasm::Error), +} + +impl Cmd { + pub async fn run(&self) -> Result<(), Error> { + let res_str = self.run_and_get_contract_id().await?; + println!("{res_str}"); + Ok(()) + } + + pub async fn run_and_get_contract_id(&self) -> Result { + let wasm_hash = if let Some(wasm) = &self.wasm { + let hash = install::Cmd { + wasm: wasm::Args { wasm: wasm.clone() }, + config: self.config.clone(), + fee: self.fee.clone(), + ignore_checks: self.ignore_checks, + } + .run_and_get_hash() + .await?; + hex::encode(hash) + } else { + self.wasm_hash + .as_ref() + .ok_or(Error::WasmNotProvided)? + .to_string() + }; + + let hash = Hash(utils::contract_id_from_str(&wasm_hash).map_err(|e| { + Error::CannotParseWasmHash { + wasm_hash: wasm_hash.clone(), + error: e, + } + })?); + + self.run_against_rpc_server(hash).await + } + + async fn run_against_rpc_server(&self, wasm_hash: Hash) -> Result { + let network = self.config.get_network()?; + let salt: [u8; 32] = match &self.salt { + Some(h) => soroban_spec_tools::utils::padded_hex_from_str(h, 32) + .map_err(|_| Error::CannotParseSalt { salt: h.clone() })? + .try_into() + .map_err(|_| Error::CannotParseSalt { salt: h.clone() })?, + None => rand::thread_rng().gen::<[u8; 32]>(), + }; + + let client = Client::new(&network.rpc_url)?; + client + .verify_network_passphrase(Some(&network.network_passphrase)) + .await?; + let key = self.config.key_pair()?; + + // Get the account sequence number + let public_strkey = + stellar_strkey::ed25519::PublicKey(key.verifying_key().to_bytes()).to_string(); + + let account_details = client.get_account(&public_strkey).await?; + let sequence: i64 = account_details.seq_num.into(); + let (tx, contract_id) = build_create_contract_tx( + wasm_hash, + sequence + 1, + self.fee.fee, + &network.network_passphrase, + salt, + &key, + )?; + client + .prepare_and_send_transaction(&tx, &key, &[], &network.network_passphrase, None, None) + .await?; + Ok(stellar_strkey::Contract(contract_id.0).to_string()) + } +} + +fn build_create_contract_tx( + hash: Hash, + sequence: i64, + fee: u32, + network_passphrase: &str, + salt: [u8; 32], + key: &ed25519_dalek::SigningKey, +) -> Result<(Transaction, Hash), Error> { + let source_account = AccountId(PublicKey::PublicKeyTypeEd25519( + key.verifying_key().to_bytes().into(), + )); + + let contract_id_preimage = ContractIdPreimage::Address(ContractIdPreimageFromAddress { + address: ScAddress::Account(source_account), + salt: Uint256(salt), + }); + let contract_id = get_contract_id(contract_id_preimage.clone(), network_passphrase)?; + + let op = Operation { + source_account: None, + body: OperationBody::InvokeHostFunction(InvokeHostFunctionOp { + host_function: HostFunction::CreateContract(CreateContractArgs { + contract_id_preimage, + executable: ContractExecutable::Wasm(hash), + }), + auth: VecM::default(), + }), + }; + let tx = Transaction { + source_account: MuxedAccount::Ed25519(Uint256(key.verifying_key().to_bytes())), + fee, + seq_num: SequenceNumber(sequence), + cond: Preconditions::None, + memo: Memo::None, + operations: vec![op].try_into()?, + ext: TransactionExt::V0, + }; + + Ok((tx, Hash(contract_id.into()))) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_build_create_contract() { + let hash = hex::decode("0000000000000000000000000000000000000000000000000000000000000000") + .unwrap() + .try_into() + .unwrap(); + let result = build_create_contract_tx( + Hash(hash), + 300, + 1, + "Public Global Stellar Network ; September 2015", + [0u8; 32], + &utils::parse_secret_key("SBFGFF27Y64ZUGFAIG5AMJGQODZZKV2YQKAVUUN4HNE24XZXD2OEUVUP") + .unwrap(), + ); + + assert!(result.is_ok()); + } +} diff --git a/cmd/soroban-cli/src/commands/contract/fetch.rs b/cmd/soroban-cli/src/commands/contract/fetch.rs index 9929f3832..61a82fc47 100644 --- a/cmd/soroban-cli/src/commands/contract/fetch.rs +++ b/cmd/soroban-cli/src/commands/contract/fetch.rs @@ -20,7 +20,7 @@ use soroban_spec::read::FromWasmError; use stellar_strkey::DecodeError; use super::super::config::{self, locator}; -use crate::commands::config::network::{self, Network}; +use crate::commands::network::{self, Network}; use crate::{ rpc::{self, Client}, utils, Pwd, diff --git a/cmd/soroban-cli/src/commands/contract/id.rs b/cmd/soroban-cli/src/commands/contract/id.rs new file mode 100644 index 000000000..bb8744d51 --- /dev/null +++ b/cmd/soroban-cli/src/commands/contract/id.rs @@ -0,0 +1,28 @@ +pub mod asset; +pub mod wasm; + +#[derive(Debug, clap::Subcommand)] +pub enum Cmd { + /// Deploy builtin Soroban Asset Contract + Asset(asset::Cmd), + /// Deploy normal Wasm Contract + Wasm(wasm::Cmd), +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Asset(#[from] asset::Error), + #[error(transparent)] + Wasm(#[from] wasm::Error), +} + +impl Cmd { + pub fn run(&self) -> Result<(), Error> { + match &self { + Cmd::Asset(asset) => asset.run()?, + Cmd::Wasm(wasm) => wasm.run()?, + } + Ok(()) + } +} diff --git a/cmd/soroban-cli/src/commands/lab/token/id.rs b/cmd/soroban-cli/src/commands/contract/id/asset.rs similarity index 100% rename from cmd/soroban-cli/src/commands/lab/token/id.rs rename to cmd/soroban-cli/src/commands/contract/id/asset.rs diff --git a/cmd/soroban-cli/src/commands/contract/id/wasm.rs b/cmd/soroban-cli/src/commands/contract/id/wasm.rs new file mode 100644 index 000000000..9c02f07d2 --- /dev/null +++ b/cmd/soroban-cli/src/commands/contract/id/wasm.rs @@ -0,0 +1,68 @@ +use clap::{arg, command, Parser}; +use sha2::{Digest, Sha256}; +use soroban_env_host::xdr::{ + self, AccountId, ContractIdPreimage, ContractIdPreimageFromAddress, Hash, HashIdPreimage, + HashIdPreimageContractId, Limits, PublicKey, ScAddress, Uint256, WriteXdr, +}; + +use crate::commands::config; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + /// ID of the Soroban contract + #[arg(long)] + pub salt: String, + + #[command(flatten)] + pub config: config::Args, +} +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + ParseError(#[from] crate::utils::parsing::Error), + #[error(transparent)] + ConfigError(#[from] crate::commands::config::Error), + #[error(transparent)] + Xdr(#[from] xdr::Error), + #[error("cannot parse salt {0}")] + CannotParseSalt(String), +} +impl Cmd { + pub fn run(&self) -> Result<(), Error> { + let salt: [u8; 32] = soroban_spec_tools::utils::padded_hex_from_str(&self.salt, 32) + .map_err(|_| Error::CannotParseSalt(self.salt.clone()))? + .try_into() + .map_err(|_| Error::CannotParseSalt(self.salt.clone()))?; + let contract_id_preimage = + contract_preimage(&self.config.key_pair()?.verifying_key(), salt); + let contract_id = get_contract_id( + contract_id_preimage.clone(), + &self.config.get_network()?.network_passphrase, + )?; + let strkey_contract_id = stellar_strkey::Contract(contract_id.0).to_string(); + println!("{strkey_contract_id}"); + Ok(()) + } +} + +pub fn contract_preimage(key: &ed25519_dalek::VerifyingKey, salt: [u8; 32]) -> ContractIdPreimage { + let source_account = AccountId(PublicKey::PublicKeyTypeEd25519(key.to_bytes().into())); + ContractIdPreimage::Address(ContractIdPreimageFromAddress { + address: ScAddress::Account(source_account), + salt: Uint256(salt), + }) +} + +pub fn get_contract_id( + contract_id_preimage: ContractIdPreimage, + network_passphrase: &str, +) -> Result { + let network_id = Hash(Sha256::digest(network_passphrase.as_bytes()).into()); + let preimage = HashIdPreimage::ContractId(HashIdPreimageContractId { + network_id, + contract_id_preimage, + }); + let preimage_xdr = preimage.to_xdr(Limits::none())?; + Ok(Hash(Sha256::digest(preimage_xdr).into())) +} diff --git a/cmd/soroban-cli/src/commands/contract/invoke.rs b/cmd/soroban-cli/src/commands/contract/invoke.rs index 2b6322b88..669342b06 100644 --- a/cmd/soroban-cli/src/commands/contract/invoke.rs +++ b/cmd/soroban-cli/src/commands/contract/invoke.rs @@ -185,8 +185,8 @@ impl Cmd { if let Some(mut val) = matches_.get_raw(&name) { let mut s = val.next().unwrap().to_string_lossy().to_string(); if matches!(i.type_, ScSpecTypeDef::Address) { - let cmd = crate::commands::config::identity::address::Cmd { - name: Some(s.clone()), + let cmd = crate::commands::keys::address::Cmd { + name: s.clone(), hd_path: Some(0), locator: self.config.locator.clone(), }; diff --git a/cmd/soroban-cli/src/commands/contract/mod.rs b/cmd/soroban-cli/src/commands/contract/mod.rs index c10c31502..35be97a70 100644 --- a/cmd/soroban-cli/src/commands/contract/mod.rs +++ b/cmd/soroban-cli/src/commands/contract/mod.rs @@ -1,8 +1,10 @@ +pub mod asset; pub mod bindings; pub mod build; pub mod deploy; pub mod extend; pub mod fetch; +pub mod id; pub mod inspect; pub mod install; pub mod invoke; @@ -14,6 +16,9 @@ use crate::commands::global; #[derive(Debug, clap::Subcommand)] pub enum Cmd { + /// Utilities to deploy a Stellar Asset Contract or get its id + #[command(subcommand)] + Asset(asset::Cmd), /// Generate code client bindings for a contract #[command(subcommand)] Bindings(bindings::Cmd), @@ -25,12 +30,16 @@ pub enum Cmd { /// If no keys are specified the contract itself is extended. Extend(extend::Cmd), - /// Deploy a contract - Deploy(deploy::Cmd), + /// Deploy a wasm contract + Deploy(deploy::wasm::Cmd), /// Fetch a contract's Wasm binary Fetch(fetch::Cmd), + /// Generate the contract id for a given contract or asset + #[command(subcommand)] + Id(id::Cmd), + /// Inspect a WASM file listing contract functions, meta, etc Inspect(inspect::Cmd), @@ -61,6 +70,9 @@ pub enum Cmd { #[derive(thiserror::Error, Debug)] pub enum Error { + #[error(transparent)] + Asset(#[from] asset::Error), + #[error(transparent)] Bindings(#[from] bindings::Error), @@ -71,10 +83,12 @@ pub enum Error { Extend(#[from] extend::Error), #[error(transparent)] - Deploy(#[from] deploy::Error), + Deploy(#[from] deploy::wasm::Error), #[error(transparent)] Fetch(#[from] fetch::Error), + #[error(transparent)] + Id(#[from] id::Error), #[error(transparent)] Inspect(#[from] inspect::Error), @@ -98,10 +112,12 @@ pub enum Error { impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { match &self { + Cmd::Asset(asset) => asset.run().await?, Cmd::Bindings(bindings) => bindings.run().await?, Cmd::Build(build) => build.run()?, Cmd::Extend(extend) => extend.run().await?, Cmd::Deploy(deploy) => deploy.run().await?, + Cmd::Id(id) => id.run()?, Cmd::Inspect(inspect) => inspect.run()?, Cmd::Install(install) => install.run().await?, Cmd::Invoke(invoke) => invoke.run(global_args).await?, diff --git a/cmd/soroban-cli/src/commands/events.rs b/cmd/soroban-cli/src/commands/events.rs index 676052053..aa46bbe23 100644 --- a/cmd/soroban-cli/src/commands/events.rs +++ b/cmd/soroban-cli/src/commands/events.rs @@ -3,7 +3,7 @@ use std::io; use soroban_env_host::xdr::{self, Limits, ReadXdr}; -use super::config::{locator, network}; +use super::{config::locator, network}; use crate::{rpc, utils}; #[derive(Parser, Debug, Clone)] diff --git a/cmd/soroban-cli/src/commands/config/identity/add.rs b/cmd/soroban-cli/src/commands/keys/add.rs similarity index 93% rename from cmd/soroban-cli/src/commands/config/identity/add.rs rename to cmd/soroban-cli/src/commands/keys/add.rs index 7cea70fd7..2868c7371 100644 --- a/cmd/soroban-cli/src/commands/config/identity/add.rs +++ b/cmd/soroban-cli/src/commands/keys/add.rs @@ -1,6 +1,7 @@ -use super::super::{locator, secret}; use clap::command; +use super::super::config::{locator, secret}; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] diff --git a/cmd/soroban-cli/src/commands/config/identity/address.rs b/cmd/soroban-cli/src/commands/keys/address.rs similarity index 70% rename from cmd/soroban-cli/src/commands/config/identity/address.rs rename to cmd/soroban-cli/src/commands/keys/address.rs index f965f2d27..d13381b49 100644 --- a/cmd/soroban-cli/src/commands/config/identity/address.rs +++ b/cmd/soroban-cli/src/commands/keys/address.rs @@ -1,6 +1,6 @@ -use crate::commands::config::secret::Secret; +use crate::commands::config::secret; -use super::super::{locator, secret}; +use super::super::config::locator; use clap::arg; #[derive(thiserror::Error, Debug)] @@ -19,7 +19,7 @@ pub enum Error { #[group(skip)] pub struct Cmd { /// Name of identity to lookup, default test identity used if not provided - pub name: Option, + pub name: String, /// If identity is a seed phrase use this hd path, default is 0 #[arg(long)] @@ -36,20 +36,14 @@ impl Cmd { } pub fn private_key(&self) -> Result { - Ok(if let Some(name) = &self.name { - self.locator.read_identity(name)? - } else { - Secret::test_seed_phrase()? - } - .key_pair(self.hd_path)?) + Ok(self + .locator + .read_identity(&self.name)? + .key_pair(self.hd_path)?) } pub fn public_key(&self) -> Result { - if let Some(Ok(key)) = self - .name - .as_deref() - .map(stellar_strkey::ed25519::PublicKey::from_string) - { + if let Ok(key) = stellar_strkey::ed25519::PublicKey::from_string(&self.name) { Ok(key) } else { Ok(stellar_strkey::ed25519::PublicKey::from_payload( diff --git a/cmd/soroban-cli/src/commands/config/identity/fund.rs b/cmd/soroban-cli/src/commands/keys/fund.rs similarity index 94% rename from cmd/soroban-cli/src/commands/config/identity/fund.rs rename to cmd/soroban-cli/src/commands/keys/fund.rs index 1f2155b17..b6c088f13 100644 --- a/cmd/soroban-cli/src/commands/config/identity/fund.rs +++ b/cmd/soroban-cli/src/commands/keys/fund.rs @@ -1,6 +1,6 @@ use clap::command; -use crate::commands::config::network; +use crate::commands::network; use super::address; diff --git a/cmd/soroban-cli/src/commands/config/identity/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs similarity index 88% rename from cmd/soroban-cli/src/commands/config/identity/generate.rs rename to cmd/soroban-cli/src/commands/keys/generate.rs index 76a6073d8..07782b216 100644 --- a/cmd/soroban-cli/src/commands/config/identity/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -1,7 +1,9 @@ use clap::{arg, command}; -use super::super::{ - locator, network, +use crate::commands::network; + +use super::super::config::{ + locator, secret::{self, Secret}, }; @@ -20,7 +22,9 @@ pub enum Error { pub struct Cmd { /// Name of identity pub name: String, - + /// Do not fund address + #[arg(long)] + pub no_fund: bool, /// Optional seed to use when generating seed phrase. /// Random otherwise. #[arg(long, conflicts_with = "default_seed")] @@ -54,15 +58,12 @@ impl Cmd { Secret::from_seed(self.seed.as_deref()) }?; let secret = if self.as_secret { - let secret = seed_phrase.private_key(self.hd_path)?; - Secret::SecretKey { - secret_key: secret.to_string(), - } + seed_phrase.private_key(self.hd_path)?.into() } else { seed_phrase }; self.config_locator.write_identity(&self.name, &secret)?; - if !self.network.is_no_network() { + if !self.no_fund { let addr = secret.public_key(self.hd_path)?; let network = self.network.get(&self.config_locator)?; network.fund_address(&addr).await.unwrap_or_else(|_| { diff --git a/cmd/soroban-cli/src/commands/keys/ls.rs b/cmd/soroban-cli/src/commands/keys/ls.rs new file mode 100644 index 000000000..bc46ffcd8 --- /dev/null +++ b/cmd/soroban-cli/src/commands/keys/ls.rs @@ -0,0 +1,45 @@ +use clap::command; + +use super::super::config::locator; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Config(#[from] locator::Error), +} + +#[derive(Debug, clap::Parser, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub config_locator: locator::Args, + + #[arg(long, short = 'l')] + pub long: bool, +} + +impl Cmd { + pub fn run(&self) -> Result<(), Error> { + let res = if self.long { self.ls_l() } else { self.ls() }?.join("\n"); + println!("{res}"); + Ok(()) + } + + pub fn ls(&self) -> Result, Error> { + let mut list = self.config_locator.list_identities()?; + let test = "test".to_string(); + if !list.contains(&test) { + list.push(test); + } + Ok(list) + } + + pub fn ls_l(&self) -> Result, Error> { + Ok(self + .config_locator + .list_identities_long()? + .into_iter() + .map(|(name, location)| format!("{location}\nName: {name}\n")) + .collect::>()) + } +} diff --git a/cmd/soroban-cli/src/commands/config/identity/mod.rs b/cmd/soroban-cli/src/commands/keys/mod.rs similarity index 100% rename from cmd/soroban-cli/src/commands/config/identity/mod.rs rename to cmd/soroban-cli/src/commands/keys/mod.rs diff --git a/cmd/soroban-cli/src/commands/config/identity/rm.rs b/cmd/soroban-cli/src/commands/keys/rm.rs similarity index 92% rename from cmd/soroban-cli/src/commands/config/identity/rm.rs rename to cmd/soroban-cli/src/commands/keys/rm.rs index 6018a4ef1..df48108d3 100644 --- a/cmd/soroban-cli/src/commands/config/identity/rm.rs +++ b/cmd/soroban-cli/src/commands/keys/rm.rs @@ -1,6 +1,7 @@ -use super::super::locator; use clap::command; +use super::super::config::locator; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] diff --git a/cmd/soroban-cli/src/commands/config/identity/show.rs b/cmd/soroban-cli/src/commands/keys/show.rs similarity index 75% rename from cmd/soroban-cli/src/commands/config/identity/show.rs rename to cmd/soroban-cli/src/commands/keys/show.rs index 58a9d709d..b99478cbc 100644 --- a/cmd/soroban-cli/src/commands/config/identity/show.rs +++ b/cmd/soroban-cli/src/commands/keys/show.rs @@ -1,6 +1,7 @@ -use super::super::{locator, secret}; use clap::arg; +use super::super::config::{locator, secret}; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] @@ -17,7 +18,7 @@ pub enum Error { #[group(skip)] pub struct Cmd { /// Name of identity to lookup, default is test identity - pub name: Option, + pub name: String, /// If identity is a seed phrase use this hd path, default is 0 #[arg(long)] @@ -34,11 +35,9 @@ impl Cmd { } pub fn private_key(&self) -> Result { - Ok(if let Some(name) = &self.name { - self.locator.read_identity(name)? - } else { - secret::Secret::test_seed_phrase()? - } - .private_key(self.hd_path)?) + Ok(self + .locator + .read_identity(&self.name)? + .private_key(self.hd_path)?) } } diff --git a/cmd/soroban-cli/src/commands/lab/mod.rs b/cmd/soroban-cli/src/commands/lab/mod.rs index 96d64094d..f405efe6d 100644 --- a/cmd/soroban-cli/src/commands/lab/mod.rs +++ b/cmd/soroban-cli/src/commands/lab/mod.rs @@ -1,4 +1,5 @@ use clap::Subcommand; +use stellar_xdr::cli as xdr; pub mod token; @@ -8,7 +9,7 @@ pub enum Cmd { Token(token::Root), /// Decode xdr - Xdr(stellar_xdr::cli::Root), + Xdr(xdr::Root), } #[derive(thiserror::Error, Debug)] @@ -16,7 +17,7 @@ pub enum Error { #[error(transparent)] Token(#[from] token::Error), #[error(transparent)] - Xdr(#[from] stellar_xdr::cli::Error), + Xdr(#[from] xdr::Error), } impl Cmd { diff --git a/cmd/soroban-cli/src/commands/lab/token/mod.rs b/cmd/soroban-cli/src/commands/lab/token/mod.rs index ab6eb7117..bd7eacf36 100644 --- a/cmd/soroban-cli/src/commands/lab/token/mod.rs +++ b/cmd/soroban-cli/src/commands/lab/token/mod.rs @@ -1,10 +1,8 @@ use std::fmt::Debug; +use crate::commands::contract::{deploy, id}; use clap::{Parser, Subcommand}; -pub mod id; -pub mod wrap; - #[derive(Parser, Debug)] pub struct Root { #[clap(subcommand)] @@ -14,17 +12,19 @@ pub struct Root { #[derive(Subcommand, Debug)] enum Cmd { /// Deploy a token contract to wrap an existing Stellar classic asset for smart contract usage - Wrap(wrap::Cmd), + /// Deprecated, use `soroban contract deploy asset` instead + Wrap(deploy::asset::Cmd), /// Compute the expected contract id for the given asset - Id(id::Cmd), + /// Deprecated, use `soroban contract id asset` instead + Id(id::asset::Cmd), } #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] - Wrap(#[from] wrap::Error), + Wrap(#[from] deploy::asset::Error), #[error(transparent)] - Id(#[from] id::Error), + Id(#[from] id::asset::Error), } impl Root { diff --git a/cmd/soroban-cli/src/commands/mod.rs b/cmd/soroban-cli/src/commands/mod.rs index 76152261d..952869af3 100644 --- a/cmd/soroban-cli/src/commands/mod.rs +++ b/cmd/soroban-cli/src/commands/mod.rs @@ -7,7 +7,9 @@ pub mod config; pub mod contract; pub mod events; pub mod global; +pub mod keys; pub mod lab; +pub mod network; pub mod plugin; pub mod version; @@ -90,11 +92,13 @@ impl Root { pub async fn run(&mut self) -> Result<(), Error> { match &mut self.cmd { Cmd::Completion(completion) => completion.run(), - Cmd::Config(config) => config.run().await?, Cmd::Contract(contract) => contract.run(&self.global_args).await?, Cmd::Events(events) => events.run().await?, Cmd::Lab(lab) => lab.run().await?, + Cmd::Network(network) => network.run()?, Cmd::Version(version) => version.run(), + Cmd::Keys(id) => id.run().await?, + Cmd::Config(c) => c.run().await?, }; Ok(()) } @@ -113,17 +117,23 @@ pub enum Cmd { /// Print shell completion code for the specified shell. #[command(long_about = completion::LONG_ABOUT)] Completion(completion::Cmd), + /// Deprecated, use `soroban keys` and `soroban network` instead + #[command(subcommand)] + Config(config::Cmd), /// Tools for smart contract developers #[command(subcommand)] Contract(contract::Cmd), - /// Read and update config - #[command(subcommand)] - Config(config::Cmd), /// Watch the network for contract events Events(events::Cmd), + /// Create and manage identities including keys and addresses + #[command(subcommand)] + Keys(keys::Cmd), /// Experiment with early features and expert tools #[command(subcommand)] Lab(lab::Cmd), + /// Start and configure networks + #[command(subcommand)] + Network(network::Cmd), /// Print version information Version(version::Cmd), } @@ -135,7 +145,8 @@ pub enum Error { Contract(#[from] contract::Error), #[error(transparent)] Events(#[from] events::Error), - + #[error(transparent)] + Keys(#[from] keys::Error), #[error(transparent)] Lab(#[from] lab::Error), #[error(transparent)] @@ -144,4 +155,6 @@ pub enum Error { Clap(#[from] clap::error::Error), #[error(transparent)] Plugin(#[from] plugin::Error), + #[error(transparent)] + Network(#[from] network::Error), } diff --git a/cmd/soroban-cli/src/commands/config/network/add.rs b/cmd/soroban-cli/src/commands/network/add.rs similarity index 93% rename from cmd/soroban-cli/src/commands/config/network/add.rs rename to cmd/soroban-cli/src/commands/network/add.rs index 3ab9a8b17..b6a2ddd38 100644 --- a/cmd/soroban-cli/src/commands/config/network/add.rs +++ b/cmd/soroban-cli/src/commands/network/add.rs @@ -1,4 +1,4 @@ -use super::{super::secret, locator}; +use super::super::config::{locator, secret}; use clap::command; #[derive(thiserror::Error, Debug)] diff --git a/cmd/soroban-cli/src/commands/config/network/ls.rs b/cmd/soroban-cli/src/commands/network/ls.rs similarity index 100% rename from cmd/soroban-cli/src/commands/config/network/ls.rs rename to cmd/soroban-cli/src/commands/network/ls.rs diff --git a/cmd/soroban-cli/src/commands/config/network/mod.rs b/cmd/soroban-cli/src/commands/network/mod.rs similarity index 92% rename from cmd/soroban-cli/src/commands/config/network/mod.rs rename to cmd/soroban-cli/src/commands/network/mod.rs index 59b1d7971..22cba1904 100644 --- a/cmd/soroban-cli/src/commands/config/network/mod.rs +++ b/cmd/soroban-cli/src/commands/network/mod.rs @@ -10,7 +10,7 @@ use crate::{ rpc::{self, Client}, }; -use super::locator; +use super::config::locator; pub mod add; pub mod ls; @@ -40,7 +40,7 @@ pub enum Error { #[error(transparent)] Config(#[from] locator::Error), - #[error("network arg or rpc url and network passphrase are required if using the network")] + #[error("network arg or rpc url and network passphrase are required if using the network")] Network, #[error(transparent)] Rpc(#[from] rpc::Error), @@ -74,6 +74,7 @@ pub struct Args { #[arg( long = "rpc-url", requires = "network_passphrase", + required_unless_present = "network", env = "SOROBAN_RPC_URL", help_heading = HEADING_RPC, )] @@ -82,6 +83,7 @@ pub struct Args { #[arg( long = "network-passphrase", requires = "rpc_url", + required_unless_present = "network", env = "SOROBAN_NETWORK_PASSPHRASE", help_heading = HEADING_RPC, )] @@ -89,8 +91,7 @@ pub struct Args { /// Name of network to use from config #[arg( long, - conflicts_with = "network_passphrase", - conflicts_with = "rpc_url", + required_unless_present = "rpc_url", env = "SOROBAN_NETWORK", help_heading = HEADING_RPC, )] @@ -100,8 +101,11 @@ pub struct Args { impl Args { pub fn get(&self, locator: &locator::Args) -> Result { if let Some(name) = self.network.as_deref() { - Ok(locator.read_network(name)?) - } else if let (Some(rpc_url), Some(network_passphrase)) = + 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 { @@ -112,10 +116,6 @@ impl Args { Err(Error::Network) } } - - pub fn is_no_network(&self) -> bool { - self.network.is_none() && self.network_passphrase.is_none() && self.rpc_url.is_none() - } } #[derive(Debug, clap::Args, Serialize, Deserialize, Clone)] diff --git a/cmd/soroban-cli/src/commands/config/network/rm.rs b/cmd/soroban-cli/src/commands/network/rm.rs similarity index 100% rename from cmd/soroban-cli/src/commands/config/network/rm.rs rename to cmd/soroban-cli/src/commands/network/rm.rs diff --git a/cmd/soroban-rpc/internal/test/cli_test.go b/cmd/soroban-rpc/internal/test/cli_test.go index 1cef8e8e9..997372ed8 100644 --- a/cmd/soroban-rpc/internal/test/cli_test.go +++ b/cmd/soroban-rpc/internal/test/cli_test.go @@ -51,7 +51,7 @@ func TestCLIWrapCustom(t *testing.T) { it := NewCLITest(t) assetCode := "deadbeef" issuerAccount := getCLIDefaultAccount(t) - strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("lab token wrap --asset=%s:%s", assetCode, issuerAccount)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract asset deploy --asset=%s:%s", assetCode, issuerAccount)) require.Equal(t, "true", runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- authorized --id=%s", strkeyContractID, issuerAccount))) asset := txnbuild.CreditAsset{ Code: assetCode, @@ -65,7 +65,7 @@ func TestCLIWrapCustom(t *testing.T) { func TestCLIWrapNative(t *testing.T) { NewCLITest(t) testAccount := getCLIDefaultAccount(t) - strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("lab token wrap --asset=native:%s", testAccount)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract asset deploy --asset=native:%s", testAccount)) require.Equal(t, "CAMTHSPKXZJIRTUXQP5QWJIFH3XIDMKLFAWVQOFOXPTKAW5GKV37ZC4N", strkeyContractID) require.Equal(t, "true", runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- authorized --id=%s", strkeyContractID, testAccount))) require.Equal(t, "\"9223372036854775807\"", runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- balance --id %s", strkeyContractID, testAccount))) @@ -285,12 +285,14 @@ func runCLICommand(t *testing.T, cmd string) *icmd.Result { c.Env = append(os.Environ(), fmt.Sprintf("SOROBAN_RPC_URL=http://localhost:%d/", sorobanRPCPort), fmt.Sprintf("SOROBAN_NETWORK_PASSPHRASE=%s", StandaloneNetworkPassphrase), + "SOROBAN_ACCOUNT=test", ) return icmd.RunCmd(c) } func getCLIDefaultAccount(t *testing.T) string { - return runSuccessfulCLICmd(t, "config identity address --hd-path 0") + runSuccessfulCLICmd(t, "keys generate -d test --no-fund") + return "GDIY6AQQ75WMD4W46EYB7O6UYMHOCGQHLAQGQTKHDX4J2DYQCHVCR4W4" } func NewCLITest(t *testing.T) *Test { diff --git a/docs/soroban-cli-full-docs.md b/docs/soroban-cli-full-docs.md index 7be027c82..3546594c6 100644 --- a/docs/soroban-cli-full-docs.md +++ b/docs/soroban-cli-full-docs.md @@ -6,7 +6,23 @@ This document contains the help content for the `soroban` command-line program. * [`soroban`↴](#soroban) * [`soroban completion`↴](#soroban-completion) +* [`soroban config`↴](#soroban-config) +* [`soroban config network`↴](#soroban-config-network) +* [`soroban config network add`↴](#soroban-config-network-add) +* [`soroban config network rm`↴](#soroban-config-network-rm) +* [`soroban config network ls`↴](#soroban-config-network-ls) +* [`soroban config identity`↴](#soroban-config-identity) +* [`soroban config identity add`↴](#soroban-config-identity-add) +* [`soroban config identity address`↴](#soroban-config-identity-address) +* [`soroban config identity fund`↴](#soroban-config-identity-fund) +* [`soroban config identity generate`↴](#soroban-config-identity-generate) +* [`soroban config identity ls`↴](#soroban-config-identity-ls) +* [`soroban config identity rm`↴](#soroban-config-identity-rm) +* [`soroban config identity show`↴](#soroban-config-identity-show) * [`soroban contract`↴](#soroban-contract) +* [`soroban contract asset`↴](#soroban-contract-asset) +* [`soroban contract asset id`↴](#soroban-contract-asset-id) +* [`soroban contract asset deploy`↴](#soroban-contract-asset-deploy) * [`soroban contract bindings`↴](#soroban-contract-bindings) * [`soroban contract bindings json`↴](#soroban-contract-bindings-json) * [`soroban contract bindings rust`↴](#soroban-contract-bindings-rust) @@ -15,26 +31,24 @@ This document contains the help content for the `soroban` command-line program. * [`soroban contract extend`↴](#soroban-contract-extend) * [`soroban contract deploy`↴](#soroban-contract-deploy) * [`soroban contract fetch`↴](#soroban-contract-fetch) +* [`soroban contract id`↴](#soroban-contract-id) +* [`soroban contract id asset`↴](#soroban-contract-id-asset) +* [`soroban contract id wasm`↴](#soroban-contract-id-wasm) * [`soroban contract inspect`↴](#soroban-contract-inspect) * [`soroban contract install`↴](#soroban-contract-install) * [`soroban contract invoke`↴](#soroban-contract-invoke) * [`soroban contract optimize`↴](#soroban-contract-optimize) * [`soroban contract read`↴](#soroban-contract-read) * [`soroban contract restore`↴](#soroban-contract-restore) -* [`soroban config`↴](#soroban-config) -* [`soroban config identity`↴](#soroban-config-identity) -* [`soroban config identity add`↴](#soroban-config-identity-add) -* [`soroban config identity address`↴](#soroban-config-identity-address) -* [`soroban config identity fund`↴](#soroban-config-identity-fund) -* [`soroban config identity generate`↴](#soroban-config-identity-generate) -* [`soroban config identity ls`↴](#soroban-config-identity-ls) -* [`soroban config identity rm`↴](#soroban-config-identity-rm) -* [`soroban config identity show`↴](#soroban-config-identity-show) -* [`soroban config network`↴](#soroban-config-network) -* [`soroban config network add`↴](#soroban-config-network-add) -* [`soroban config network rm`↴](#soroban-config-network-rm) -* [`soroban config network ls`↴](#soroban-config-network-ls) * [`soroban events`↴](#soroban-events) +* [`soroban keys`↴](#soroban-keys) +* [`soroban keys add`↴](#soroban-keys-add) +* [`soroban keys address`↴](#soroban-keys-address) +* [`soroban keys fund`↴](#soroban-keys-fund) +* [`soroban keys generate`↴](#soroban-keys-generate) +* [`soroban keys ls`↴](#soroban-keys-ls) +* [`soroban keys rm`↴](#soroban-keys-rm) +* [`soroban keys show`↴](#soroban-keys-show) * [`soroban lab`↴](#soroban-lab) * [`soroban lab token`↴](#soroban-lab-token) * [`soroban lab token wrap`↴](#soroban-lab-token-wrap) @@ -46,6 +60,10 @@ This document contains the help content for the `soroban` command-line program. * [`soroban lab xdr decode`↴](#soroban-lab-xdr-decode) * [`soroban lab xdr encode`↴](#soroban-lab-xdr-encode) * [`soroban lab xdr version`↴](#soroban-lab-xdr-version) +* [`soroban network`↴](#soroban-network) +* [`soroban network add`↴](#soroban-network-add) +* [`soroban network rm`↴](#soroban-network-rm) +* [`soroban network ls`↴](#soroban-network-ls) * [`soroban version`↴](#soroban-version) ## `soroban` @@ -80,16 +98,18 @@ Full CLI reference: https://github.com/stellar/soroban-tools/tree/main/docs/soro ###### **Subcommands:** * `completion` — Print shell completion code for the specified shell +* `config` — Deprecated, use `soroban keys` and `soroban network` instead * `contract` — Tools for smart contract developers -* `config` — Read and update config * `events` — Watch the network for contract events +* `keys` — Create and manage identities including keys and addresses * `lab` — Experiment with early features and expert tools +* `network` — Start and configure networks * `version` — Print version information ###### **Options:** * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." * `-f`, `--filter-logs ` — Filter logs output. To turn on "soroban_cli::log::footprint=debug" or off "=off". Can also use env var `RUST_LOG` * `-q`, `--quiet` — Do not write logs to stderr including `INFO` * `-v`, `--verbose` — Log DEBUG events @@ -122,6 +142,233 @@ To enable autocomplete permanently, run: +## `soroban config` + +Deprecated, use `soroban keys` and `soroban network` instead + +**Usage:** `soroban config ` + +###### **Subcommands:** + +* `network` — Configure different networks. Depraecated, use `soroban network` instead +* `identity` — Identity management. Deprecated, use `soroban keys` instead + + + +## `soroban config network` + +Configure different networks. Depraecated, use `soroban network` instead + +**Usage:** `soroban config network ` + +###### **Subcommands:** + +* `add` — Add a new network +* `rm` — Remove a network +* `ls` — List networks + + + +## `soroban config network add` + +Add a new network + +**Usage:** `soroban config network add [OPTIONS] --rpc-url --network-passphrase ` + +###### **Arguments:** + +* `` — Name of network + +###### **Options:** + +* `--rpc-url ` — RPC server endpoint +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `soroban config network rm` + +Remove a network + +**Usage:** `soroban config network rm [OPTIONS] ` + +###### **Arguments:** + +* `` — Network to remove + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `soroban config network ls` + +List networks + +**Usage:** `soroban config network ls [OPTIONS]` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `-l`, `--long` — Get more info about the networks + + + +## `soroban config identity` + +Identity management. Deprecated, use `soroban keys` instead + +**Usage:** `soroban config identity ` + +###### **Subcommands:** + +* `add` — Add a new identity (keypair, ledger, macOS keychain) +* `address` — Given an identity return its address (public key) +* `fund` — Fund an identity on a test network +* `generate` — Generate a new identity with a seed phrase, currently 12 words +* `ls` — List identities +* `rm` — Remove an identity +* `show` — Given an identity return its private key + + + +## `soroban config identity add` + +Add a new identity (keypair, ledger, macOS keychain) + +**Usage:** `soroban config identity add [OPTIONS] ` + +###### **Arguments:** + +* `` — Name of identity + +###### **Options:** + +* `--secret-key` — Add using secret_key Can provide with SOROBAN_SECRET_KEY +* `--seed-phrase` — Add using 12 word seed phrase to generate secret_key +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `soroban config identity address` + +Given an identity return its address (public key) + +**Usage:** `soroban config identity address [OPTIONS] ` + +###### **Arguments:** + +* `` — Name of identity to lookup, default test identity used if not provided + +###### **Options:** + +* `--hd-path ` — If identity is a seed phrase use this hd path, default is 0 +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `soroban config identity fund` + +Fund an identity on a test network + +**Usage:** `soroban config identity fund [OPTIONS] ` + +###### **Arguments:** + +* `` — Name of identity to lookup, default test identity used if not provided + +###### **Options:** + +* `--rpc-url ` — RPC server endpoint +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--hd-path ` — If identity is a seed phrase use this hd path, default is 0 +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `soroban config identity generate` + +Generate a new identity with a seed phrase, currently 12 words + +**Usage:** `soroban config identity generate [OPTIONS] ` + +###### **Arguments:** + +* `` — Name of identity + +###### **Options:** + +* `--no-fund` — Do not fund address +* `--seed ` — Optional seed to use when generating seed phrase. Random otherwise +* `-s`, `--as-secret` — Output the generated identity as a secret key +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--hd-path ` — When generating a secret key, which hd_path should be used from the original seed_phrase +* `-d`, `--default-seed` — Generate the default seed phrase. Useful for testing. Equivalent to --seed 0000000000000000 +* `--rpc-url ` — RPC server endpoint +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config + + + +## `soroban config identity ls` + +List identities + +**Usage:** `soroban config identity ls [OPTIONS]` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `-l`, `--long` + + + +## `soroban config identity rm` + +Remove an identity + +**Usage:** `soroban config identity rm [OPTIONS] ` + +###### **Arguments:** + +* `` — Identity to remove + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `soroban config identity show` + +Given an identity return its private key + +**Usage:** `soroban config identity show [OPTIONS] ` + +###### **Arguments:** + +* `` — Name of identity to lookup, default is test identity + +###### **Options:** + +* `--hd-path ` — If identity is a seed phrase use this hd path, default is 0 +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + ## `soroban contract` Tools for smart contract developers @@ -130,11 +377,13 @@ Tools for smart contract developers ###### **Subcommands:** +* `asset` — Utilities to deploy a Stellar Asset Contract or get its id * `bindings` — Generate code client bindings for a contract * `build` — Build a contract from source * `extend` — Extend the time to live ledger of a contract-data ledger entry -* `deploy` — Deploy a contract +* `deploy` — Deploy a wasm contract * `fetch` — Fetch a contract's Wasm binary +* `id` — Generate the contract id for a given contract or asset * `inspect` — Inspect a WASM file listing contract functions, meta, etc * `install` — Install a WASM file to the ledger without creating a contract instance * `invoke` — Invoke a contract function @@ -144,6 +393,60 @@ Tools for smart contract developers +## `soroban contract asset` + +Utilities to deploy a Stellar Asset Contract or get its id + +**Usage:** `soroban contract asset ` + +###### **Subcommands:** + +* `id` — Get Id of builtin Soroban Asset Contract. Deprecated, use `soroban contract id asset` instead +* `deploy` — Deploy builtin Soroban Asset Contract + + + +## `soroban contract asset id` + +Get Id of builtin Soroban Asset Contract. Deprecated, use `soroban contract id asset` instead + +**Usage:** `soroban contract asset id [OPTIONS] --asset --source-account ` + +###### **Options:** + +* `--asset ` — ID of the Stellar classic asset to wrap, e.g. "USDC:G...5" +* `--rpc-url ` — RPC server endpoint +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `soroban contract asset deploy` + +Deploy builtin Soroban Asset Contract + +**Usage:** `soroban contract asset deploy [OPTIONS] --asset --source-account ` + +###### **Options:** + +* `--asset ` — ID of the Stellar classic asset to wrap, e.g. "USDC:G...5" +* `--rpc-url ` — RPC server endpoint +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm + + Default value: `100` + + + ## `soroban contract bindings` Generate code client bindings for a contract @@ -195,7 +498,7 @@ Generate a TypeScript / JavaScript package * `--overwrite` — Whether to overwrite output directory if it already exists * `--contract-id ` — The contract ID/address on the network * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config @@ -235,7 +538,7 @@ Extend the time to live ledger of a contract-data ledger entry. If no keys are specified the contract itself is extended. -**Usage:** `soroban contract extend [OPTIONS] --ledgers-to-extend --durability ` +**Usage:** `soroban contract extend [OPTIONS] --ledgers-to-extend --durability --source-account ` ###### **Options:** @@ -260,7 +563,7 @@ If no keys are specified the contract itself is extended. * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." * `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm Default value: `100` @@ -269,9 +572,9 @@ If no keys are specified the contract itself is extended. ## `soroban contract deploy` -Deploy a contract +Deploy a wasm contract -**Usage:** `soroban contract deploy [OPTIONS] <--wasm |--wasm-hash >` +**Usage:** `soroban contract deploy [OPTIONS] --source-account <--wasm |--wasm-hash >` ###### **Options:** @@ -284,7 +587,7 @@ Deploy a contract * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." * `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm Default value: `100` @@ -305,10 +608,61 @@ Fetch a contract's Wasm binary * `--id ` — Contract ID to fetch * `-o`, `--out-file ` — Where to write output otherwise stdout is used * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." +* `--rpc-url ` — RPC server endpoint +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config + + + +## `soroban contract id` + +Generate the contract id for a given contract or asset + +**Usage:** `soroban contract id ` + +###### **Subcommands:** + +* `asset` — Deploy builtin Soroban Asset Contract +* `wasm` — Deploy normal Wasm Contract + + + +## `soroban contract id asset` + +Deploy builtin Soroban Asset Contract + +**Usage:** `soroban contract id asset [OPTIONS] --asset --source-account ` + +###### **Options:** + +* `--asset ` — ID of the Stellar classic asset to wrap, e.g. "USDC:G...5" +* `--rpc-url ` — RPC server endpoint +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `soroban contract id wasm` + +Deploy normal Wasm Contract + +**Usage:** `soroban contract id wasm [OPTIONS] --salt --source-account ` + +###### **Options:** + +* `--salt ` — ID of the Soroban contract * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config +* `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." @@ -334,7 +688,7 @@ Inspect a WASM file listing contract functions, meta, etc Pretty print of contract spec entries * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." @@ -342,7 +696,7 @@ Inspect a WASM file listing contract functions, meta, etc Install a WASM file to the ledger without creating a contract instance -**Usage:** `soroban contract install [OPTIONS] --wasm ` +**Usage:** `soroban contract install [OPTIONS] --source-account --wasm ` ###### **Options:** @@ -352,7 +706,7 @@ Install a WASM file to the ledger without creating a contract instance * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." * `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm Default value: `100` @@ -371,7 +725,7 @@ Generates an "implicit CLI" for the specified contract on-the-fly using the cont soroban contract invoke ... -- --help -**Usage:** `soroban contract invoke [OPTIONS] --id [-- ...]` +**Usage:** `soroban contract invoke [OPTIONS] --id --source-account [-- ...]` ###### **Arguments:** @@ -387,7 +741,7 @@ soroban contract invoke ... -- --help * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." * `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm Default value: `100` @@ -411,7 +765,7 @@ Optimize a WASM file Print the current value of a contract-data ledger entry -**Usage:** `soroban contract read [OPTIONS] --durability ` +**Usage:** `soroban contract read [OPTIONS] --durability --source-account ` ###### **Options:** @@ -446,7 +800,7 @@ Print the current value of a contract-data ledger entry * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." @@ -456,7 +810,7 @@ Restore an evicted value for a contract-data legder entry. If no keys are specificed the contract itself is restored. -**Usage:** `soroban contract restore [OPTIONS] --durability ` +**Usage:** `soroban contract restore [OPTIONS] --durability --source-account ` ###### **Options:** @@ -481,31 +835,59 @@ If no keys are specificed the contract itself is restored. * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." * `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm Default value: `100` -## `soroban config` +## `soroban events` -Read and update config +Watch the network for contract events -**Usage:** `soroban config ` +**Usage:** `soroban events [OPTIONS]` -###### **Subcommands:** +###### **Options:** + +* `--start-ledger ` — The first ledger sequence number in the range to pull events https://developers.stellar.org/docs/encyclopedia/ledger-headers#ledger-sequence +* `--cursor ` — The cursor corresponding to the start of the event range +* `--output ` — Output formatting options for event stream -* `identity` — Configure different identities to sign transactions -* `network` — Configure different networks + Default value: `pretty` + Possible values: + - `pretty`: + Colorful, human-oriented console output + - `plain`: + Human-oriented console output without colors + - `json`: + JSONified console output +* `-c`, `--count ` — The maximum number of events to display (defer to the server-defined limit) -## `soroban config identity` + Default value: `10` +* `--id ` — A set of (up to 5) contract IDs to filter events on. This parameter can be passed multiple times, e.g. `--id C123.. --id C456..`, or passed with multiple parameters, e.g. `--id C123 C456` +* `--topic ` — A set of (up to 4) topic filters to filter event topics on. A single topic filter can contain 1-4 different segment filters, separated by commas, with an asterisk (* character) indicating a wildcard segment +* `--type ` — Specifies which type of contract events to display -Configure different identities to sign transactions + Default value: `all` -**Usage:** `soroban config identity ` + Possible values: `all`, `contract`, `system` + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--rpc-url ` — RPC server endpoint +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config + + + +## `soroban keys` + +Create and manage identities including keys and addresses + +**Usage:** `soroban keys ` ###### **Subcommands:** @@ -519,11 +901,11 @@ Configure different identities to sign transactions -## `soroban config identity add` +## `soroban keys add` Add a new identity (keypair, ledger, macOS keychain) -**Usage:** `soroban config identity add [OPTIONS] ` +**Usage:** `soroban keys add [OPTIONS] ` ###### **Arguments:** @@ -534,15 +916,15 @@ Add a new identity (keypair, ledger, macOS keychain) * `--secret-key` — Add using secret_key Can provide with SOROBAN_SECRET_KEY * `--seed-phrase` — Add using 12 word seed phrase to generate secret_key * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." -## `soroban config identity address` +## `soroban keys address` Given an identity return its address (public key) -**Usage:** `soroban config identity address [OPTIONS] [NAME]` +**Usage:** `soroban keys address [OPTIONS] ` ###### **Arguments:** @@ -552,15 +934,15 @@ Given an identity return its address (public key) * `--hd-path ` — If identity is a seed phrase use this hd path, default is 0 * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." -## `soroban config identity fund` +## `soroban keys fund` Fund an identity on a test network -**Usage:** `soroban config identity fund [OPTIONS] [NAME]` +**Usage:** `soroban keys fund [OPTIONS] ` ###### **Arguments:** @@ -573,15 +955,15 @@ Fund an identity on a test network * `--network ` — Name of network to use from config * `--hd-path ` — If identity is a seed phrase use this hd path, default is 0 * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." -## `soroban config identity generate` +## `soroban keys generate` Generate a new identity with a seed phrase, currently 12 words -**Usage:** `soroban config identity generate [OPTIONS] ` +**Usage:** `soroban keys generate [OPTIONS] ` ###### **Arguments:** @@ -589,10 +971,11 @@ Generate a new identity with a seed phrase, currently 12 words ###### **Options:** +* `--no-fund` — Do not fund address * `--seed ` — Optional seed to use when generating seed phrase. Random otherwise * `-s`, `--as-secret` — Output the generated identity as a secret key * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." * `--hd-path ` — When generating a secret key, which hd_path should be used from the original seed_phrase * `-d`, `--default-seed` — Generate the default seed phrase. Useful for testing. Equivalent to --seed 0000000000000000 * `--rpc-url ` — RPC server endpoint @@ -601,24 +984,25 @@ Generate a new identity with a seed phrase, currently 12 words -## `soroban config identity ls` +## `soroban keys ls` List identities -**Usage:** `soroban config identity ls [OPTIONS]` +**Usage:** `soroban keys ls [OPTIONS]` ###### **Options:** * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." +* `-l`, `--long` -## `soroban config identity rm` +## `soroban keys rm` Remove an identity -**Usage:** `soroban config identity rm [OPTIONS] ` +**Usage:** `soroban keys rm [OPTIONS] ` ###### **Arguments:** @@ -627,15 +1011,15 @@ Remove an identity ###### **Options:** * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." -## `soroban config identity show` +## `soroban keys show` Given an identity return its private key -**Usage:** `soroban config identity show [OPTIONS] [NAME]` +**Usage:** `soroban keys show [OPTIONS] ` ###### **Arguments:** @@ -645,112 +1029,7 @@ Given an identity return its private key * `--hd-path ` — If identity is a seed phrase use this hd path, default is 0 * `--global` — Use global config -* `--config-dir ` - - - -## `soroban config network` - -Configure different networks - -**Usage:** `soroban config network ` - -###### **Subcommands:** - -* `add` — Add a new network -* `rm` — Remove a network -* `ls` — List networks - - - -## `soroban config network add` - -Add a new network - -**Usage:** `soroban config network add [OPTIONS] --rpc-url --network-passphrase ` - -###### **Arguments:** - -* `` — Name of network - -###### **Options:** - -* `--rpc-url ` — RPC server endpoint -* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server -* `--global` — Use global config -* `--config-dir ` - - - -## `soroban config network rm` - -Remove a network - -**Usage:** `soroban config network rm [OPTIONS] ` - -###### **Arguments:** - -* `` — Network to remove - -###### **Options:** - -* `--global` — Use global config -* `--config-dir ` - - - -## `soroban config network ls` - -List networks - -**Usage:** `soroban config network ls [OPTIONS]` - -###### **Options:** - -* `--global` — Use global config -* `--config-dir ` -* `-l`, `--long` — Get more info about the networks - - - -## `soroban events` - -Watch the network for contract events - -**Usage:** `soroban events [OPTIONS]` - -###### **Options:** - -* `--start-ledger ` — The first ledger sequence number in the range to pull events https://developers.stellar.org/docs/encyclopedia/ledger-headers#ledger-sequence -* `--cursor ` — The cursor corresponding to the start of the event range -* `--output ` — Output formatting options for event stream - - Default value: `pretty` - - Possible values: - - `pretty`: - Colorful, human-oriented console output - - `plain`: - Human-oriented console output without colors - - `json`: - JSONified console output - -* `-c`, `--count ` — The maximum number of events to display (defer to the server-defined limit) - - Default value: `10` -* `--id ` — A set of (up to 5) contract IDs to filter events on. This parameter can be passed multiple times, e.g. `--id C123.. --id C456..`, or passed with multiple parameters, e.g. `--id C123 C456` -* `--topic ` — A set of (up to 4) topic filters to filter event topics on. A single topic filter can contain 1-4 different segment filters, separated by commas, with an asterisk (* character) indicating a wildcard segment -* `--type ` — Specifies which type of contract events to display - - Default value: `all` - - Possible values: `all`, `contract`, `system` - -* `--global` — Use global config -* `--config-dir ` -* `--rpc-url ` — RPC server endpoint -* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server -* `--network ` — Name of network to use from config +* `--config-dir ` — Location of config directory, default is "." @@ -775,16 +1054,16 @@ Wrap, create, and manage token contracts ###### **Subcommands:** -* `wrap` — Deploy a token contract to wrap an existing Stellar classic asset for smart contract usage -* `id` — Compute the expected contract id for the given asset +* `wrap` — Deploy a token contract to wrap an existing Stellar classic asset for smart contract usage Deprecated, use `soroban contract deploy asset` instead +* `id` — Compute the expected contract id for the given asset Deprecated, use `soroban contract id asset` instead ## `soroban lab token wrap` -Deploy a token contract to wrap an existing Stellar classic asset for smart contract usage +Deploy a token contract to wrap an existing Stellar classic asset for smart contract usage Deprecated, use `soroban contract deploy asset` instead -**Usage:** `soroban lab token wrap [OPTIONS] --asset ` +**Usage:** `soroban lab token wrap [OPTIONS] --asset --source-account ` ###### **Options:** @@ -795,7 +1074,7 @@ Deploy a token contract to wrap an existing Stellar classic asset for smart cont * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." * `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm Default value: `100` @@ -804,9 +1083,9 @@ Deploy a token contract to wrap an existing Stellar classic asset for smart cont ## `soroban lab token id` -Compute the expected contract id for the given asset +Compute the expected contract id for the given asset Deprecated, use `soroban contract id asset` instead -**Usage:** `soroban lab token id [OPTIONS] --asset ` +**Usage:** `soroban lab token id [OPTIONS] --asset --source-account ` ###### **Options:** @@ -817,7 +1096,7 @@ Compute the expected contract id for the given asset * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config -* `--config-dir ` +* `--config-dir ` — Location of config directory, default is "." @@ -967,6 +1246,70 @@ Print version information +## `soroban network` + +Start and configure networks + +**Usage:** `soroban network ` + +###### **Subcommands:** + +* `add` — Add a new network +* `rm` — Remove a network +* `ls` — List networks + + + +## `soroban network add` + +Add a new network + +**Usage:** `soroban network add [OPTIONS] --rpc-url --network-passphrase ` + +###### **Arguments:** + +* `` — Name of network + +###### **Options:** + +* `--rpc-url ` — RPC server endpoint +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `soroban network rm` + +Remove a network + +**Usage:** `soroban network rm [OPTIONS] ` + +###### **Arguments:** + +* `` — Network to remove + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `soroban network ls` + +List networks + +**Usage:** `soroban network ls [OPTIONS]` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `-l`, `--long` — Get more info about the networks + + + ## `soroban version` Print version information