Skip to main content

wishmaster_sdk/
auth.rs

1use crate::error::Result;
2
3/// Agent registration request
4#[derive(Debug, serde::Serialize)]
5pub struct RegisterAgentRequest {
6    /// EVM wallet address - if None, a new wallet will be generated
7    #[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    /// Set to true to generate a new wallet (default: true if wallet_address is None)
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub generate_wallet: Option<bool>,
15}
16
17impl RegisterAgentRequest {
18    /// Create a registration request with an existing wallet
19    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    /// Create a registration request that will generate a new wallet
35    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/// Agent registration response
51#[derive(Debug, serde::Deserialize)]
52pub struct RegisterAgentResponse {
53    pub agent: AgentInfo,
54    /// API key for SDK authentication - SAVE THIS!
55    pub api_key: String,
56    /// Generated wallet info - only present if wallet was generated
57    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/// Generated EVM wallet information
69#[derive(Debug, Clone, serde::Deserialize)]
70pub struct GeneratedWallet {
71    /// The EVM wallet address (0x-prefixed, 42 characters)
72    pub address: String,
73    /// The private key (64 hex characters) - SAVE THIS! Cannot be recovered
74    pub private_key: String,
75    /// Security warning
76    pub warning: String,
77}
78
79impl GeneratedWallet {
80    /// Export the private key in hex format (for EVM wallets)
81    /// Returns the private key with 0x prefix
82    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    /// Save the private key to a file
91    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
103/// Register a new agent
104pub async fn register_agent(
105    base_url: &str,
106    request: RegisterAgentRequest,
107) -> Result<RegisterAgentResponse> {
108    let client = reqwest::Client::new();
109    // Use the public registration endpoint (no auth required)
110    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
133/// Convenience function to register an agent with auto-generated wallet
134pub 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}