Skip to content

Commit

Permalink
feat: add signer to other commands and ban keys named "ledger"
Browse files Browse the repository at this point in the history
  • Loading branch information
willemneal committed Jun 24, 2024
1 parent 957d451 commit eb04955
Show file tree
Hide file tree
Showing 18 changed files with 373 additions and 157 deletions.
100 changes: 99 additions & 1 deletion FULL_HELP_DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ This document contains the help content for the `stellar` command-line program.
* [`stellar version`](#stellar-version)
* [`stellar tx`](#stellar-tx)
* [`stellar tx simulate`](#stellar-tx-simulate)
* [`stellar tx sign`](#stellar-tx-sign)
* [`stellar tx send`](#stellar-tx-send)
* [`stellar cache`](#stellar-cache)
* [`stellar cache clean`](#stellar-cache-clean)
* [`stellar cache path`](#stellar-cache-path)
Expand Down Expand Up @@ -217,6 +219,10 @@ Get Id of builtin Soroban Asset Contract. Deprecated, use `stellar contract id a
Possible values: `true`, `false`

* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--check` — Check with user before signature. Eventually this will be replaced with `--yes`, which does the opposite and will force a check without --yes

Possible values: `true`, `false`




Expand All @@ -239,6 +245,10 @@ Deploy builtin Soroban Asset Contract
Possible values: `true`, `false`

* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--check` — Check with user before signature. Eventually this will be replaced with `--yes`, which does the opposite and will force a check without --yes

Possible values: `true`, `false`

* `--fee <FEE>` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm

Default value: `100`
Expand Down Expand Up @@ -398,6 +408,10 @@ If no keys are specified the contract itself is extended.
Possible values: `true`, `false`

* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--check` — Check with user before signature. Eventually this will be replaced with `--yes`, which does the opposite and will force a check without --yes

Possible values: `true`, `false`

* `--fee <FEE>` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm

Default value: `100`
Expand Down Expand Up @@ -438,6 +452,10 @@ Deploy a wasm contract
Possible values: `true`, `false`

* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--check` — Check with user before signature. Eventually this will be replaced with `--yes`, which does the opposite and will force a check without --yes

Possible values: `true`, `false`

* `--fee <FEE>` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm

Default value: `100`
Expand Down Expand Up @@ -517,6 +535,10 @@ Deploy builtin Soroban Asset Contract
Possible values: `true`, `false`

* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--check` — Check with user before signature. Eventually this will be replaced with `--yes`, which does the opposite and will force a check without --yes

Possible values: `true`, `false`




Expand All @@ -539,6 +561,10 @@ Deploy normal Wasm Contract
Possible values: `true`, `false`

* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--check` — Check with user before signature. Eventually this will be replaced with `--yes`, which does the opposite and will force a check without --yes

Possible values: `true`, `false`




Expand Down Expand Up @@ -611,6 +637,10 @@ Install a WASM file to the ledger without creating a contract instance
Possible values: `true`, `false`

* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--check` — Check with user before signature. Eventually this will be replaced with `--yes`, which does the opposite and will force a check without --yes

Possible values: `true`, `false`

* `--fee <FEE>` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm

Default value: `100`
Expand Down Expand Up @@ -668,6 +698,10 @@ stellar contract invoke ... -- --help
Possible values: `true`, `false`

* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--check` — Check with user before signature. Eventually this will be replaced with `--yes`, which does the opposite and will force a check without --yes

Possible values: `true`, `false`

* `--fee <FEE>` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm

Default value: `100`
Expand Down Expand Up @@ -745,6 +779,10 @@ Print the current value of a contract-data ledger entry
Possible values: `true`, `false`

* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--check` — Check with user before signature. Eventually this will be replaced with `--yes`, which does the opposite and will force a check without --yes

Possible values: `true`, `false`




Expand Down Expand Up @@ -788,6 +826,10 @@ If no keys are specificed the contract itself is restored.
Possible values: `true`, `false`

* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--check` — Check with user before signature. Eventually this will be replaced with `--yes`, which does the opposite and will force a check without --yes

Possible values: `true`, `false`

* `--fee <FEE>` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm

Default value: `100`
Expand Down Expand Up @@ -1436,6 +1478,8 @@ Sign, Simulate, and Send transactions
###### **Subcommands:**

* `simulate` — Simulate a transaction envelope from stdin
* `sign` — Sign a transaction with a ledger or local key
* `send` — Send a transaction envelope to the network



Expand All @@ -1450,13 +1494,67 @@ Simulate a transaction envelope from stdin
* `--rpc-url <RPC_URL>` — RPC server endpoint
* `--network-passphrase <NETWORK_PASSPHRASE>` — Network passphrase to sign the transaction sent to the rpc server
* `--network <NETWORK>` — Name of network to use from config
* `--source-account <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…")
* `--source-account <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 <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

Possible values: `true`, `false`

* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--check` — Check with user before signature. Eventually this will be replaced with `--yes`, which does the opposite and will force a check without --yes

Possible values: `true`, `false`




## `stellar tx sign`

Sign a transaction with a ledger or local key

**Usage:** `stellar tx sign [OPTIONS] --source-account <SOURCE_ACCOUNT>`

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

* `--rpc-url <RPC_URL>` — RPC server endpoint
* `--network-passphrase <NETWORK_PASSPHRASE>` — Network passphrase to sign the transaction sent to the rpc server
* `--network <NETWORK>` — Name of network to use from config
* `--source-account <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 <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

Possible values: `true`, `false`

* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--check` — Check with user before signature. Eventually this will be replaced with `--yes`, which does the opposite and will force a check without --yes

Possible values: `true`, `false`




## `stellar tx send`

Send a transaction envelope to the network

**Usage:** `stellar tx send [OPTIONS] --source-account <SOURCE_ACCOUNT>`

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

* `--rpc-url <RPC_URL>` — RPC server endpoint
* `--network-passphrase <NETWORK_PASSPHRASE>` — Network passphrase to sign the transaction sent to the rpc server
* `--network <NETWORK>` — Name of network to use from config
* `--source-account <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 <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

Possible values: `true`, `false`

* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."
* `--check` — Check with user before signature. Eventually this will be replaced with `--yes`, which does the opposite and will force a check without --yes

Possible values: `true`, `false`




Expand Down
4 changes: 3 additions & 1 deletion cmd/crates/soroban-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ impl TestEnv {
config_dir,
},
hd_path: None,
check: false,
}
}

Expand Down Expand Up @@ -263,9 +264,10 @@ impl TestEnv {
}

/// Returns the public key corresponding to the test keys's `hd_path`
pub fn test_address(&self, hd_path: usize) -> String {
pub async fn test_address(&self, hd_path: usize) -> String {
self.cmd::<keys::address::Cmd>(&format!("--hd-path={hd_path}"))
.public_key()
.await
.unwrap()
.to_string()
}
Expand Down
30 changes: 30 additions & 0 deletions cmd/crates/soroban-test/tests/it/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,36 @@ fn read_key() {
.stdout(predicates::str::contains("test_id\n"));
}

#[test]
fn cannot_generate_ledger_key() {
let sandbox = TestEnv::default();
sandbox
.new_assert_cmd("keys")
.arg("generate")
.arg("ledger")
.assert()
.stdout("")
.stderr("error: Cannot name a Key ledger\n")
.failure();
}

#[test]
fn cannot_add_ledger_key() {
let sandbox = TestEnv::default();
sandbox
.new_assert_cmd("keys")
.env(
"SOROBAN_SECRET_KEY",
"SDIY6AQQ75WMD4W46EYB7O6UYMHOCGQHLAQGQTKHDX4J2DYQCHVCQYFD",
)
.arg("add")
.arg("ledger")
.assert()
.stdout("")
.stderr("error: Cannot name a Key ledger\n")
.failure();
}

#[test]
fn generate_key() {
let sandbox = TestEnv::default();
Expand Down
6 changes: 3 additions & 3 deletions cmd/crates/soroban-test/tests/it/util.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::Path;

use soroban_cli::commands::{
config::{locator::KeyType, secret::Secret},
config::{locator::KeyType, secret::SignerKind},
contract,
};
use soroban_test::{TestEnv, Wasm, TEST_ACCOUNT};
Expand All @@ -17,10 +17,10 @@ pub enum SecretKind {
#[allow(clippy::needless_pass_by_value)]
pub fn add_key(dir: &Path, name: &str, kind: SecretKind, data: &str) {
let secret = match kind {
SecretKind::Seed => Secret::SeedPhrase {
SecretKind::Seed => SignerKind::SeedPhrase {
seed_phrase: data.to_string(),
},
SecretKind::Key => Secret::SecretKey {
SecretKind::Key => SignerKind::SecretKey {
secret_key: data.to_string(),
},
};
Expand Down
40 changes: 37 additions & 3 deletions cmd/soroban-cli/src/commands/config/locator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use stellar_strkey::DecodeError;

use crate::{utils::find_config_dir, Pwd};

use super::{alias, network::Network, secret::Secret};
use super::{alias, network::Network, secret::SignerKind};

#[derive(thiserror::Error, Debug)]
pub enum Error {
Expand Down Expand Up @@ -65,6 +65,10 @@ pub enum Error {
CannotAccessConfigDir,
#[error("cannot parse contract ID {0}: {1}")]
CannotParseContractId(String, DecodeError),
#[error("Incorrect Key name")]
IncorrectKeyName,
#[error("Cannot name a Key ledger")]
LedgerKeyName,
}

#[derive(Debug, clap::Args, Default, Clone)]
Expand Down Expand Up @@ -98,6 +102,27 @@ impl Display for Location {
}
}

pub struct KeyName(String);

impl std::ops::Deref for KeyName {
type Target = str;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl FromStr for KeyName {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
if s == "ledger" {
return Err(Error::LedgerKeyName);
}
Ok(KeyName(s.to_string()))
}
}

impl AsRef<Path> for Location {
fn as_ref(&self) -> &Path {
match self {
Expand Down Expand Up @@ -144,7 +169,7 @@ impl Args {
)
}

pub fn write_identity(&self, name: &str, secret: &Secret) -> Result<(), Error> {
pub fn write_identity(&self, name: &KeyName, secret: &SignerKind) -> Result<(), Error> {
KeyType::Identity.write(name, secret, &self.config_dir()?)
}

Expand Down Expand Up @@ -197,10 +222,19 @@ impl Args {
})
.collect::<Vec<_>>())
}
pub fn read_identity(&self, name: &str) -> Result<Secret, Error> {

pub fn read_identity(&self, name: &str) -> Result<SignerKind, Error> {
KeyType::Identity.read_with_global(name, &self.local_config()?)
}

pub fn account(&self, account_str: &str) -> Result<SignerKind, Error> {
if let Ok(secret) = self.read_identity(account_str) {
Ok(secret)
} else {
Ok(account_str.parse::<SignerKind>()?)
}
}

pub fn read_network(&self, name: &str) -> Result<Network, Error> {
let res = KeyType::Network.read_with_global(name, &self.local_config()?);
if let Err(Error::ConfigMissing(_, _)) = &res {
Expand Down
Loading

0 comments on commit eb04955

Please sign in to comment.