use crate::error::VeilError;
use crate::intent::sign::SignedIntent;
#[derive(Debug, Clone)]
pub struct SubmitResponse {
pub tx_hash: String,
pub status: String,
}
#[derive(Debug, Clone)]
pub struct Client {
base_url: String,
}
impl Client {
pub fn new(base_url: &str) -> Self {
let url = base_url.trim_end_matches('/');
Self {
base_url: url.to_string(),
}
}
pub fn submit(&self, signed_intent: &SignedIntent) -> Result<SubmitResponse, VeilError> {
let url = format!("{}/intents", self.base_url);
let body = signed_intent.to_json()?;
let response = reqwest::blocking::Client::new()
.post(&url)
.header("Content-Type", "application/json")
.body(body)
.send()
.map_err(|e| VeilError::Http(format!("request failed: {}", e)))?;
let status = response.status();
let response_text = response
.text()
.map_err(|e| VeilError::Http(format!("failed to read response: {}", e)))?;
if !status.is_success() {
return Err(VeilError::Http(format!(
"node returned status {}: {}",
status, response_text
)));
}
let parsed: serde_json::Value = serde_json::from_str(&response_text)
.map_err(|e| VeilError::Http(format!("invalid JSON response: {}", e)))?;
let tx_hash = parsed["tx_hash"]
.as_str()
.ok_or_else(|| VeilError::Http("missing tx_hash in response".to_string()))?
.to_string();
let status_str = parsed["status"]
.as_str()
.ok_or_else(|| VeilError::Http("missing status in response".to_string()))?
.to_string();
Ok(SubmitResponse {
tx_hash,
status: status_str,
})
}
pub fn base_url(&self) -> &str {
&self.base_url
}
}