Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 65 additions & 1 deletion FULL_HELP_DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Anything after the `--` double dash (the "slop") is parsed as arguments to the c
- `snapshot` — Download a snapshot of a ledger from an archive
- `tx` — Sign, Simulate, and Send transactions
- `xdr` — Decode and encode XDR
- `strkey` — Decode and encode strkey
- `completion` — Print shell completion code for the specified shell
- `cache` — Cache for transactions and contract specs
- `version` — Print version information
Expand Down Expand Up @@ -1292,12 +1293,16 @@ Output an identity's secret key

Set the default identity that will be used on all commands. This allows you to skip `--source-account` or setting a environment variable, while reusing this value in all commands that require it

**Usage:** `stellar keys use [OPTIONS] <NAME>`
**Usage:** `stellar keys use [OPTIONS] [NAME]`

###### **Arguments:**

- `<NAME>` — Set the default network name

###### **Options:**

- `--clear` — Clear the default source account

###### **Options (Global):**

- `--global` — ⚠️ Deprecated: global config is always on
Expand Down Expand Up @@ -4141,6 +4146,65 @@ Print version information

**Usage:** `stellar xdr version`

## `stellar strkey`

Decode and encode strkey

**Usage:** `stellar strkey <COMMAND>`

###### **Subcommands:**

- `decode` — Decode strkey
- `encode` — Encode strkey
- `zero` — Generate the zero strkey
- `version` — Print version information

## `stellar strkey decode`

Decode strkey

**Usage:** `stellar strkey decode <STRKEY>`

###### **Arguments:**

- `<STRKEY>` — Strkey to decode

## `stellar strkey encode`

Encode strkey

**Usage:** `stellar strkey encode <JSON>`

###### **Arguments:**

- `<JSON>` — JSON for Strkey to encode

## `stellar strkey zero`

Generate the zero strkey

**Usage:** `stellar strkey zero [OPTIONS] <STRKEY>`

###### **Arguments:**

- `<STRKEY>` — Strkey type to generate the zero value for

Possible values: `public_key_ed25519`, `pre_auth_tx`, `hash_x`, `muxed_account_ed25519`, `signed_payload_ed25519`, `contract`, `liquidity_pool`, `claimable_balance_v0`

###### **Options:**

- `--output <OUTPUT>` — Output format

Default value: `strkey`

Possible values: `strkey`, `json`

## `stellar strkey version`

Print version information

**Usage:** `stellar strkey version`

## `stellar completion`

Print shell completion code for the specified shell
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ endif
REPOSITORY_BRANCH := "$(shell git rev-parse --abbrev-ref HEAD)"
BUILD_TIMESTAMP ?= $(shell date '+%Y-%m-%dT%H:%M:%S')

SOROBAN_PORT?=8000
STELLAR_PORT?=8000

# The following works around incompatibility between the rust and the go linkers -
# the rust would generate an object file with min-version of 13.0 where-as the go
Expand Down Expand Up @@ -52,7 +52,7 @@ test: build-test
cargo test --workspace --exclude soroban-test --features additional-libs
cargo test -p soroban-test -- --skip integration::

# expects a quickstart container running with the rpc exposed at localhost:SOROBAN_PORT
# expects a quickstart container running with the rpc exposed at localhost:STELLAR_PORT
rpc-test:
cargo test --features it --test it -- integration --test-threads=4

Expand Down
8 changes: 4 additions & 4 deletions cmd/crates/soroban-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ impl TestEnv {
if let Ok(rpc_url) = std::env::var("STELLAR_RPC_URL") {
return Self::with_rpc_url(&rpc_url);
}
let host_port = std::env::var("SOROBAN_PORT")
let host_port = std::env::var("STELLAR_PORT")
.as_deref()
.ok()
.and_then(|n| n.parse().ok())
Expand All @@ -159,9 +159,9 @@ impl TestEnv {
let mut cmd: Command = self.bin();

cmd.arg(subcommand)
.env("SOROBAN_ACCOUNT", TEST_ACCOUNT)
.env("SOROBAN_RPC_URL", &self.network.rpc_url)
.env("SOROBAN_NETWORK_PASSPHRASE", LOCAL_NETWORK_PASSPHRASE)
.env("STELLAR_ACCOUNT", TEST_ACCOUNT)
.env("STELLAR_RPC_URL", &self.network.rpc_url)
.env("STELLAR_NETWORK_PASSPHRASE", LOCAL_NETWORK_PASSPHRASE)
.env("XDG_CONFIG_HOME", self.dir().join("config").as_os_str())
.env("XDG_DATA_HOME", self.data_dir().as_os_str())
.current_dir(self.dir());
Expand Down
6 changes: 3 additions & 3 deletions cmd/crates/soroban-test/tests/it/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ fn use_env() {
sandbox
.new_assert_cmd("keys")
.env(
"SOROBAN_SECRET_KEY",
"STELLAR_SECRET_KEY",
"SDIY6AQQ75WMD4W46EYB7O6UYMHOCGQHLAQGQTKHDX4J2DYQCHVCQYFD",
)
.arg("add")
Expand All @@ -225,7 +225,7 @@ fn set_default_identity() {
sandbox
.new_assert_cmd("keys")
.env(
"SOROBAN_SECRET_KEY",
"STELLAR_SECRET_KEY",
"SC4ZPYELVR7S7EE7KZDZN3ETFTNQHHLTUL34NUAAWZG5OK2RGJ4V2U3Z",
)
.arg("add")
Expand All @@ -245,7 +245,7 @@ fn set_default_identity() {

sandbox
.new_assert_cmd("env")
.env_remove("SOROBAN_ACCOUNT")
.env_remove("STELLAR_ACCOUNT")
.assert()
.stdout(predicate::str::contains("STELLAR_ACCOUNT=alice"))
.success();
Expand Down
102 changes: 101 additions & 1 deletion cmd/crates/soroban-test/tests/it/integration/keys.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use predicates::prelude::predicate;
use predicates::prelude::{predicate, PredicateBooleanExt};
use soroban_test::AssertExt;
use soroban_test::TestEnv;

Expand Down Expand Up @@ -143,3 +143,103 @@ async fn overwrite_identity_with_add() {
pubkey_for_identity(sandbox, "test3").trim()
);
}

#[tokio::test]
#[allow(clippy::too_many_lines)]
async fn set_default_identity() {
let sandbox = &TestEnv::new();
sandbox
.new_assert_cmd("keys")
.arg("generate")
.arg("test4")
.assert()
.success();

sandbox
.new_assert_cmd("keys")
.arg("use")
.arg("test4")
.assert()
.stderr(predicate::str::contains(
"The default source account is set to `test4`",
))
.success();
}

#[tokio::test]
#[allow(clippy::too_many_lines)]
async fn clear_default_identity() {
let sandbox = &TestEnv::new();
sandbox
.new_assert_cmd("keys")
.arg("generate")
.arg("test5")
.assert()
.success();

sandbox
.new_assert_cmd("keys")
.arg("use")
.arg("test5")
.assert()
.stderr(predicate::str::contains(
"The default source account is set to `test5`",
))
.success();

sandbox
.new_assert_cmd("env")
.env_remove("STELLAR_ACCOUNT")
.assert()
.stdout(predicate::str::contains("STELLAR_ACCOUNT=test5"))
.success();

sandbox
.new_assert_cmd("keys")
.arg("use")
.arg("--clear")
.assert()
.stderr(predicate::str::contains(
"The default source account has been cleared",
))
.success();

sandbox
.new_assert_cmd("env")
.env_remove("STELLAR_ACCOUNT")
.assert()
.stdout(predicate::str::contains("STELLAR_ACCOUNT=").not())
.success();
}

#[tokio::test]
#[allow(clippy::too_many_lines)]
async fn validate_use_without_name() {
let sandbox = &TestEnv::new();

sandbox
.new_assert_cmd("keys")
.arg("use")
.assert()
.stderr(predicate::str::contains(
"error: Identify name is required unless --clear is specified",
))
.failure();
}

#[tokio::test]
#[allow(clippy::too_many_lines)]
async fn validate_use_with_both_name_and_clear() {
let sandbox = &TestEnv::new();

sandbox
.new_assert_cmd("keys")
.arg("use")
.arg("test5")
.arg("--clear")
.assert()
.stderr(predicate::str::contains(
"error: Identify name cannot be used with --clear",
))
.failure();
}
36 changes: 29 additions & 7 deletions cmd/soroban-cli/src/commands/keys/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,23 @@ use crate::{commands::global, config::locator, print::Print};
pub enum Error {
#[error(transparent)]
Config(#[from] locator::Error),

#[error("Identify name is required unless --clear is specified")]
NameRequired,

#[error("Identify name cannot be used with --clear")]
NameWithClear,
}

#[derive(Debug, clap::Parser, Clone)]
#[group(skip)]
pub struct Cmd {
/// Set the default network name.
pub name: String,
pub name: Option<String>,

/// Clear the default source account.
#[arg(long)]
pub clear: bool,
Comment on lines -13 to +23
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we omit the clear: bool, and just make it if name is None, then clear it?


#[command(flatten)]
pub config_locator: locator::Args,
Expand All @@ -19,14 +29,26 @@ pub struct Cmd {
impl Cmd {
pub fn run(&self, global_args: &global::Args) -> Result<(), Error> {
let printer = Print::new(global_args.quiet);
let _ = self.config_locator.read_identity(&self.name)?;

self.config_locator.write_default_identity(&self.name)?;
if self.clear && self.name.is_some() {
return Err(Error::NameWithClear);
}

if !self.clear && self.name.is_none() {
return Err(Error::NameRequired);
}
Comment on lines +33 to +39
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we omitted the bool, then we wouldn't need these condition checks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having clap manage this might make it easier:

clap::ArgGroup::new("Key")
    .required(true)
    .args(& ["name", "clear"]),


if self.clear {
self.config_locator.clear_default_identity()?;
printer.infoln("The default source account has been cleared".to_string());
} else {
let name = self.name.as_ref().unwrap();
let _ = self.config_locator.read_identity(name)?;

self.config_locator.write_default_identity(name)?;

printer.infoln(format!(
"The default source account is set to `{}`",
self.name,
));
printer.infoln(format!("The default source account is set to `{name}`"));
}

Ok(())
}
Expand Down
4 changes: 4 additions & 0 deletions cmd/soroban-cli/src/config/locator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,10 @@ impl Args {
Config::new()?.set_identity(name).save()
}

pub fn clear_default_identity(&self) -> Result<(), Error> {
Config::new()?.clear_identity().save()
}

pub fn list_identities(&self) -> Result<Vec<String>, Error> {
Ok(KeyType::Identity
.list_paths(&self.local_and_global()?)?
Expand Down
6 changes: 6 additions & 0 deletions cmd/soroban-cli/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ impl Config {
self
}

#[must_use]
pub fn clear_identity(mut self) -> Self {
self.defaults.identity = None;
self
}

pub fn save(&self) -> Result<(), locator::Error> {
let toml_string = toml::to_string(&self)?;
let path = cli_config_file()?;
Expand Down
Loading