1use clap::Parser;
2use jacquard::client::BasicClient;
3use jacquard::types::string::Handle;
4use jacquard_identity::resolver::IdentityResolver;
5use miette::IntoDiagnostic;
6
7#[derive(Parser, Debug)]
8#[command(author, version, about = "Resolve a handle to its DID document")]
9struct Args {
10 /// Handle to resolve (e.g., alice.bsky.social)
11 #[arg(default_value = "pfrazee.com")]
12 handle: String,
13}
14
15#[tokio::main]
16async fn main() -> miette::Result<()> {
17 let args = Args::parse();
18
19 // Parse the handle
20 let handle = Handle::new(&args.handle)?;
21
22 // Create an unauthenticated client with identity resolver
23 let client = BasicClient::unauthenticated();
24
25 // Resolve handle to DID
26 println!("Resolving handle: {}", handle);
27 let did = client
28 .resolve_handle(&handle)
29 .await
30 .map_err(|e| miette::miette!("Failed to resolve handle: {}", e))?;
31
32 println!("DID: {}\n", did);
33
34 // Resolve DID document
35 let doc_response = client
36 .resolve_did_doc(&did)
37 .await
38 .map_err(|e| miette::miette!("Failed to resolve DID document: {}", e))?;
39
40 let doc = doc_response
41 .parse()
42 .map_err(|e| miette::miette!("Failed to parse DID document: {}", e))?;
43
44 println!("DID Document:");
45 println!("ID: {}", doc.id);
46
47 if let Some(aka) = &doc.also_known_as {
48 if !aka.is_empty() {
49 println!("\nAlso Known As:");
50 for handle in aka {
51 println!(" - {}", handle);
52 }
53 }
54 }
55
56 if let Some(verification_methods) = &doc.verification_method {
57 println!("\nVerification Methods:");
58 for method in verification_methods {
59 println!(" ID: {}", method.id);
60 println!(" Type: {}", method.r#type);
61 if let Some(controller) = &method.controller {
62 println!(" Controller: {}", controller);
63 }
64 if let Some(key) = &method.public_key_multibase {
65 println!(" Public Key (multibase): {}", key);
66 }
67 if !method.extra_data.is_empty() {
68 println!(" Extra fields: {:?}", method.extra_data);
69 }
70 println!();
71 }
72 }
73
74 if let Some(services) = &doc.service {
75 println!("Services:");
76 for service in services {
77 println!(" ID: {}", service.id);
78 println!(" Type: {}", service.r#type);
79 if let Some(endpoint) = &service.service_endpoint {
80 println!(" Endpoint: {:?}", endpoint);
81 }
82 if !service.extra_data.is_empty() {
83 println!(" Extra fields: {:?}", service.extra_data);
84 }
85 println!();
86 }
87 }
88
89 if !doc.extra_data.is_empty() {
90 for (key, value) in &doc.extra_data {
91 println!(
92 "{}: {}",
93 key,
94 serde_json::to_string_pretty(value).into_diagnostic()?
95 );
96 }
97 }
98
99 Ok(())
100}