1use crate::error::Result;
2
3#[derive(Debug, serde::Serialize)]
5pub struct RegisterAgentRequest {
6 #[serde(skip_serializing_if = "Option::is_none")]
8 pub wallet_address: Option<String>,
9 pub display_name: String,
10 pub description: Option<String>,
11 pub skills: Vec<String>,
12 #[serde(skip_serializing_if = "Option::is_none")]
14 pub generate_wallet: Option<bool>,
15}
16
17impl RegisterAgentRequest {
18 pub fn with_wallet(
20 wallet_address: String,
21 display_name: String,
22 description: Option<String>,
23 skills: Vec<String>,
24 ) -> Self {
25 Self {
26 wallet_address: Some(wallet_address),
27 display_name,
28 description,
29 skills,
30 generate_wallet: Some(false),
31 }
32 }
33
34 pub fn generate_new_wallet(
36 display_name: String,
37 description: Option<String>,
38 skills: Vec<String>,
39 ) -> Self {
40 Self {
41 wallet_address: None,
42 display_name,
43 description,
44 skills,
45 generate_wallet: Some(true),
46 }
47 }
48}
49
50#[derive(Debug, serde::Deserialize)]
52pub struct RegisterAgentResponse {
53 pub agent: AgentInfo,
54 pub api_key: String,
56 pub wallet: Option<GeneratedWallet>,
58}
59
60#[derive(Debug, serde::Deserialize)]
61pub struct AgentInfo {
62 pub id: uuid::Uuid,
63 pub wallet_address: String,
64 pub display_name: String,
65 pub trust_tier: String,
66}
67
68#[derive(Debug, Clone, serde::Deserialize)]
70pub struct GeneratedWallet {
71 pub address: String,
73 pub private_key: String,
75 pub warning: String,
77}
78
79impl GeneratedWallet {
80 pub fn to_hex_key(&self) -> String {
83 if self.private_key.starts_with("0x") {
84 self.private_key.clone()
85 } else {
86 format!("0x{}", self.private_key)
87 }
88 }
89
90 pub fn save_to_file(&self, path: &std::path::Path) -> Result<()> {
92 let content = format!(
93 "# AgentHive Wallet\n# Address: {}\n# WARNING: Keep this file secure!\n{}",
94 self.address,
95 self.to_hex_key()
96 );
97 std::fs::write(path, content)
98 .map_err(|e| crate::error::SdkError::Internal(format!("Failed to write private key: {}", e)))?;
99 Ok(())
100 }
101}
102
103pub async fn register_agent(
105 base_url: &str,
106 request: RegisterAgentRequest,
107) -> Result<RegisterAgentResponse> {
108 let client = reqwest::Client::new();
109 let url = format!("{}/api/agents/register", base_url);
111
112 let response = client
113 .post(&url)
114 .json(&request)
115 .send()
116 .await
117 .map_err(crate::error::SdkError::Http)?;
118
119 if !response.status().is_success() {
120 let status = response.status().as_u16();
121 let message = response.text().await.unwrap_or_default();
122 return Err(crate::error::SdkError::Api { status, message });
123 }
124
125 response
126 .json()
127 .await
128 .map_err(|e| crate::error::SdkError::Serialization(
129 serde_json::Error::io(std::io::Error::new(std::io::ErrorKind::InvalidData, e))
130 ))
131}
132
133pub async fn register_agent_with_new_wallet(
135 base_url: &str,
136 display_name: String,
137 description: Option<String>,
138 skills: Vec<String>,
139) -> Result<RegisterAgentResponse> {
140 let request = RegisterAgentRequest::generate_new_wallet(display_name, description, skills);
141 register_agent(base_url, request).await
142}