Skip to content

Commit 3a5d493

Browse files
feat: Identity creation (#6)
Adds three components: - icp-identity/, for managing identities - icp identity import and icp identity new for creating identities - icp identity default/--identity/icp identity principal, required for useful tests Plus scaffolding: - Env for global/cached state - icp-dirs/ for project-wide agreement on what the dirs are
1 parent 0a75217 commit 3a5d493

33 files changed

+2057
-215
lines changed

Cargo.lock

Lines changed: 486 additions & 184 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
members = [
33
"bin/icp-cli",
44
"lib/icp-canister",
5+
"lib/icp-dirs",
56
"lib/icp-fs",
67
"lib/icp-identity",
78
"lib/icp-network",
@@ -11,21 +12,52 @@ members = [
1112
resolver = "3"
1213

1314
[workspace.dependencies]
15+
bip32 = "0.5.0"
1416
camino = { version = "1.1.9", features = ["serde1"] }
1517
candid = "0.10.14"
18+
clap = { version = "4.5.3", features = ["derive"] }
19+
dialoguer = "0.11.0"
20+
directories = "6.0.0"
21+
ed25519-consensus = "2.1.0"
22+
elliptic-curve = { version = "0.13.8", features = ["sec1", "std", "pkcs8"] }
1623
fd-lock = "4.0.4"
1724
glob = "0.3.2"
1825
hex = "0.4.3"
1926
ic-agent = { version = "0.40.1" }
27+
icp-canister = { path = "lib/icp-canister" }
28+
icp-dirs = { path = "lib/icp-dirs" }
29+
icp-fs = { path = "lib/icp-fs" }
30+
icp-identity = { path = "lib/icp-identity", features = ["clap"] }
31+
icp-network = { path = "lib/icp-network" }
32+
icp-project = { path = "lib/icp-project" }
33+
itertools = "0.14.0"
34+
k256 = { version = "0.13.4", features = ["pem", "pkcs8", "std"] }
35+
p256 = { version = "0.13.2", features = ["pem", "pkcs8", "std"] }
36+
pem = "3.0.5"
37+
pkcs8 = { version = "0.10.2", features = ["encryption", "std"] }
2038
pocket-ic = "9.0.0"
39+
rand = "0.9.1"
2140
reqwest = { version = "0.12.15", default-features = false, features = [
2241
"rustls-tls",
2342
] }
43+
sec1 = { version = "0.7.3", features = ["pkcs8"] }
2444
serde = { version = "1.0", features = ["derive"] }
2545
serde_json = "1.0"
2646
serde_yaml = "0.9.34"
2747
snafu = "0.8.5"
48+
strum = { version = "0.27", features = ["derive"] }
2849
tempfile = "3"
2950
time = "0.3.9"
51+
tiny-bip39 = "2.0.0"
3052
tokio = { version = "1.45.0", features = ["macros", "rt-multi-thread"] }
3153
uuid = { version = "1.16.0", features = ["serde", "v4"] }
54+
zeroize = "1.8.1"
55+
56+
[workspace.lints.rust]
57+
missing_debug_implementations = "warn"
58+
59+
[workspace.lints.clippy]
60+
enum_variant_names = "allow"
61+
62+
[profile.dev.package.scrypt]
63+
opt-level = 3

bin/icp-cli/Cargo.toml

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,35 @@ name = "icp"
99
path = "src/main.rs"
1010

1111
[dependencies]
12-
camino = { workspace = true }
13-
clap = { version = "4.5.35", features = ["derive"] }
14-
icp-canister = { path = "../../lib/icp-canister" }
15-
icp-fs = { path = "../../lib/icp-fs" }
16-
icp-network = { path = "../../lib/icp-network" }
17-
icp-project = { path = "../../lib/icp-project" }
18-
snafu = { workspace = true }
19-
tokio = { workspace = true }
12+
bip32.workspace = true
13+
camino.workspace = true
14+
clap.workspace = true
15+
dialoguer.workspace = true
16+
elliptic-curve.workspace = true
17+
hex.workspace = true
18+
ic-agent.workspace = true
19+
icp-canister.workspace = true
20+
icp-dirs.workspace = true
21+
icp-fs.workspace = true
22+
icp-identity.workspace = true
23+
icp-network.workspace = true
24+
icp-project.workspace = true
25+
itertools.workspace = true
26+
k256.workspace = true
27+
pem.workspace = true
28+
pkcs8.workspace = true
29+
sec1.workspace = true
30+
serde.workspace = true
31+
serde_json.workspace = true
32+
snafu.workspace = true
33+
tiny-bip39.workspace = true
34+
tokio.workspace = true
2035

2136
[dev-dependencies]
2237
assert_cmd = "2"
2338
predicates = "3"
2439
reqwest = { workspace = true }
2540
camino-tempfile = "1"
41+
42+
[lints]
43+
workspace = true

bin/icp-cli/src/commands.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,33 @@
1-
use crate::commands::{build::BuildCommandError, network::NetworkCommandError};
1+
use crate::{
2+
commands::{build::BuildCommandError, network::NetworkCommandError},
3+
env::Env,
4+
};
25
use clap::{Parser, Subcommand};
6+
use identity::IdentityCommandError;
37
use snafu::Snafu;
48

59
mod build;
10+
mod identity;
611
mod network;
712

813
#[derive(Parser, Debug)]
9-
pub struct Cli {
14+
pub struct Cmd {
1015
#[command(subcommand)]
1116
subcommand: Subcmd,
1217
}
1318

1419
#[derive(Subcommand, Debug)]
1520
pub enum Subcmd {
1621
Build(build::Cmd),
17-
Network(network::Cmd),
22+
Identity(identity::IdentityCmd),
23+
Network(network::NetworkCmd),
1824
}
1925

20-
pub async fn dispatch(cli: Cli) -> Result<(), DispatchError> {
26+
pub async fn dispatch(env: &Env, cli: Cmd) -> Result<(), DispatchError> {
2127
match cli.subcommand {
2228
Subcmd::Build(opts) => build::exec(opts).await?,
23-
Subcmd::Network(opts) => network::dispatch(opts).await?,
29+
Subcmd::Identity(opts) => identity::dispatch(env, opts).await?,
30+
Subcmd::Network(opts) => network::dispatch(env, opts).await?,
2431
}
2532
Ok(())
2633
}
@@ -30,6 +37,9 @@ pub enum DispatchError {
3037
#[snafu(transparent)]
3138
Build { source: BuildCommandError },
3239

40+
#[snafu(transparent)]
41+
Identity { source: IdentityCommandError },
42+
3343
#[snafu(transparent)]
3444
Network { source: NetworkCommandError },
3545
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use crate::env::Env;
2+
use clap::{Parser, Subcommand};
3+
use snafu::Snafu;
4+
5+
mod default;
6+
mod import;
7+
mod list;
8+
mod new;
9+
mod principal;
10+
11+
#[derive(Debug, Parser)]
12+
pub struct IdentityCmd {
13+
#[command(subcommand)]
14+
subcmd: IdentitySubcmd,
15+
}
16+
17+
#[derive(Debug, Subcommand)]
18+
pub enum IdentitySubcmd {
19+
Default(default::DefaultCmd),
20+
Import(import::ImportCmd),
21+
List(list::ListCmd),
22+
New(new::NewCmd),
23+
Principal(principal::PrincipalCmd),
24+
}
25+
26+
pub async fn dispatch(env: &Env, cmd: IdentityCmd) -> Result<(), IdentityCommandError> {
27+
match cmd.subcmd {
28+
IdentitySubcmd::Default(subcmd) => default::exec(env, subcmd)?,
29+
IdentitySubcmd::Import(subcmd) => import::exec(env, subcmd)?,
30+
IdentitySubcmd::List(subcmd) => list::exec(env, subcmd)?,
31+
IdentitySubcmd::New(subcmd) => new::exec(env, subcmd)?,
32+
IdentitySubcmd::Principal(subcmd) => principal::exec(env, subcmd)?,
33+
}
34+
Ok(())
35+
}
36+
37+
#[derive(Debug, Snafu)]
38+
pub enum IdentityCommandError {
39+
#[snafu(transparent)]
40+
Default {
41+
source: default::DefaultIdentityError,
42+
},
43+
44+
#[snafu(transparent)]
45+
List { source: list::ListKeysError },
46+
47+
#[snafu(transparent)]
48+
Import { source: import::ImportCmdError },
49+
50+
#[snafu(transparent)]
51+
New { source: new::NewIdentityError },
52+
53+
#[snafu(transparent)]
54+
Principal { source: principal::PrincipalError },
55+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use crate::env::Env;
2+
use clap::Parser;
3+
use icp_identity::manifest::{change_default_identity, load_identity_defaults, load_identity_list};
4+
use snafu::Snafu;
5+
6+
#[derive(Debug, Parser)]
7+
pub struct DefaultCmd {
8+
name: Option<String>,
9+
}
10+
11+
pub fn exec(env: &Env, cmd: DefaultCmd) -> Result<(), DefaultIdentityError> {
12+
let dirs = env.dirs();
13+
if let Some(name) = cmd.name {
14+
let list = load_identity_list(dirs)?;
15+
change_default_identity(dirs, &list, &name)?;
16+
println!("Set default identity to {name}");
17+
} else {
18+
let defaults = load_identity_defaults(dirs)?;
19+
println!("{}", defaults.default);
20+
}
21+
Ok(())
22+
}
23+
24+
#[derive(Debug, Snafu)]
25+
pub enum DefaultIdentityError {
26+
#[snafu(transparent)]
27+
ChangeDefault {
28+
source: icp_identity::manifest::ChangeDefaultsError,
29+
},
30+
31+
#[snafu(transparent)]
32+
LoadList {
33+
source: icp_identity::manifest::LoadIdentityManifestError,
34+
},
35+
}

0 commit comments

Comments
 (0)