Skip to main content

soroban_cli/commands/network/root_account/
mod.rs

1use clap::Parser;
2use sha2::{Digest, Sha256};
3
4use crate::commands::global;
5use crate::config::network::passphrase;
6use crate::config::{locator, network};
7
8pub mod public_key;
9pub mod secret;
10
11#[derive(thiserror::Error, Debug)]
12pub enum Error {
13    #[error(transparent)]
14    Config(#[from] locator::Error),
15    #[error(transparent)]
16    Network(#[from] network::Error),
17    #[error(transparent)]
18    Strkey(#[from] stellar_strkey::DecodeError),
19}
20
21/// Shared arguments for resolving the network passphrase and deriving the root account seed.
22#[derive(Debug, clap::Parser, Clone)]
23#[group(skip)]
24pub struct Args {
25    // @dev: `network` and `network-passphrase` args are provided explicitly as the `rpc-url` is not needed
26    /// Network passphrase to derive the root account from
27    #[arg(long = "network-passphrase", env = "STELLAR_NETWORK_PASSPHRASE")]
28    pub network_passphrase: Option<String>,
29
30    /// Name of network to use from config
31    #[arg(long, short = 'n', env = "STELLAR_NETWORK")]
32    pub network: Option<String>,
33
34    #[command(flatten)]
35    pub locator: locator::Args,
36}
37
38impl Args {
39    /// Resolve the network passphrase and derive the 32-byte key.
40    pub fn root_key(&self) -> Result<[u8; 32], Error> {
41        // If a user explicitly provides a network passphrase, use that.
42        // Otherwise, look up the network with the typical resolution process and use its passphrase.
43        let network_passphrase = match (self.network.as_deref(), self.network_passphrase.clone()) {
44            // Fall back to testnet as the default network if no config default is set
45            (None, None) => passphrase::TESTNET.to_string(),
46            (Some(network), None) => self.locator.read_network(network)?.network_passphrase,
47            (_, Some(network_passphrase)) => network_passphrase,
48        };
49        Ok(Sha256::digest(network_passphrase.as_bytes()).into())
50    }
51}
52
53#[derive(Debug, Parser)]
54pub enum Cmd {
55    /// Output a network's root account address (public key)
56    #[command(visible_alias = "address")]
57    PublicKey(public_key::Cmd),
58
59    /// Output a network's root account secret key
60    Secret(secret::Cmd),
61}
62
63impl Cmd {
64    pub fn run(&self, _global_args: &global::Args) -> Result<(), Error> {
65        match self {
66            Cmd::PublicKey(cmd) => cmd.run()?,
67            Cmd::Secret(cmd) => cmd.run()?,
68        }
69        Ok(())
70    }
71}