Skip to content

Commit 2015ee7

Browse files
authored
Add --ledger to stellar keys fund (#2558)
1 parent b76dfb7 commit 2015ee7

3 files changed

Lines changed: 34 additions & 37 deletions

File tree

FULL_HELP_DOCS.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,15 +1169,16 @@ Given an identity return its address (public key)
11691169

11701170
Fund an identity on a test network
11711171

1172-
**Usage:** `stellar keys fund [OPTIONS] <NAME>`
1172+
**Usage:** `stellar keys fund [OPTIONS] [NAME]`
11731173

11741174
###### **Arguments:**
11751175

1176-
- `<NAME>` — Name of identity to lookup, default test identity used if not provided
1176+
- `<NAME>` — Name of identity to lookup. Required unless `--ledger` is provided
11771177

11781178
###### **Options:**
11791179

1180-
- `--hd-path <HD_PATH>` — If identity is a seed phrase use this hd path, default is 0
1180+
- `--hd-path <HD_PATH>` — If identity is a seed phrase use this hd path, default is 0. With --ledger this is the Ledger account index (default 0)
1181+
- `--ledger` — Derive the address from a connected Ledger hardware wallet at `m/44'/148'/N'`, where `N` defaults to 0 and can be set with `--hd-path`
11811182

11821183
###### **Options (Global):**
11831184

cmd/soroban-cli/src/commands/keys/fund.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,23 @@ pub struct Cmd {
1717
pub network: network::Args,
1818
/// Address to fund
1919
#[command(flatten)]
20-
pub address: public_key::Args,
20+
pub address: public_key::Cmd,
2121
}
2222

2323
impl Cmd {
2424
pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
2525
let print = Print::new(global_args.quiet);
2626
let addr = self.address.public_key().await?;
2727
let network = self.network.get(&self.address.locator)?;
28-
let formatted_name = self.address.name.to_string();
28+
let label = self
29+
.address
30+
.name
31+
.as_ref()
32+
.map_or_else(|| addr.to_string(), ToString::to_string);
2933
network.fund_address(&addr).await?;
3034
print.checkln(format!(
3135
"Account {} funded on {:?}",
32-
formatted_name, network.network_passphrase
36+
label, network.network_passphrase
3337
));
3438
Ok(())
3539
}
@@ -43,9 +47,29 @@ mod tests {
4347
const PUBLIC_KEY: &str = "GAKSH6AD2IPJQELTHIOWDAPYX74YELUOWJLI2L4RIPIPZH6YQIFNUSDC";
4448

4549
#[test]
46-
fn fund_does_not_accept_ledger_flag() {
50+
fn ledger_flag_parses_without_name() {
51+
let cmd = Cmd::try_parse_from(["fund", "--ledger"]).expect("--ledger alone parses");
52+
assert!(cmd.address.ledger);
53+
assert!(cmd.address.name.is_none());
54+
}
55+
56+
#[test]
57+
fn ledger_flag_with_hd_path_parses() {
58+
let cmd = Cmd::try_parse_from(["fund", "--ledger", "--hd-path", "5"]).unwrap();
59+
assert!(cmd.address.ledger);
60+
assert_eq!(cmd.address.hd_path, Some(5));
61+
}
62+
63+
#[test]
64+
fn ledger_flag_conflicts_with_name() {
4765
let err = Cmd::try_parse_from(["fund", PUBLIC_KEY, "--ledger"])
48-
.expect_err("`--ledger` belongs to `keys address` only");
49-
assert_eq!(err.kind(), clap::error::ErrorKind::UnknownArgument);
66+
.expect_err("--ledger + name must conflict");
67+
assert_eq!(err.kind(), clap::error::ErrorKind::ArgumentConflict);
68+
}
69+
70+
#[test]
71+
fn missing_name_without_ledger_is_rejected() {
72+
let err = Cmd::try_parse_from(["fund"]).expect_err("name is required without --ledger");
73+
assert_eq!(err.kind(), clap::error::ErrorKind::MissingRequiredArgument);
5074
}
5175
}

cmd/soroban-cli/src/commands/keys/public_key.rs

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,6 @@ pub enum Error {
1212
HdPathOutOfRange(usize),
1313
}
1414

15-
/// The fields shared by every command that resolves an identity to a public
16-
/// key. Embed this with `#[command(flatten)]` to inherit `name`, `hd_path`,
17-
/// and the config locator without picking up `keys address`'s `--ledger`
18-
/// flag.
19-
#[derive(Debug, clap::Parser, Clone)]
20-
#[group(skip)]
21-
pub struct Args {
22-
/// Name of identity to lookup, default test identity used if not provided
23-
pub name: UnresolvedMuxedAccount,
24-
25-
/// If identity is a seed phrase use this hd path, default is 0
26-
#[arg(long)]
27-
pub hd_path: Option<usize>,
28-
29-
#[command(flatten)]
30-
pub locator: locator::Args,
31-
}
32-
33-
impl Args {
34-
pub async fn public_key(&self) -> Result<stellar_strkey::ed25519::PublicKey, Error> {
35-
Ok(public_key_from_muxed(
36-
self.name
37-
.resolve_muxed_account(&self.locator, self.hd_path)
38-
.await?,
39-
))
40-
}
41-
}
42-
4315
#[derive(Debug, clap::Parser, Clone)]
4416
#[group(skip)]
4517
pub struct Cmd {

0 commit comments

Comments
 (0)