use crate::{
error::Error,
models::{
common::ApiErrorBody,
screening::{
BlockchainAddressScreeningResponse, ScreenAddressEnvelope, ScreenAddressRequest,
},
},
};
pub struct ComplianceClient {
base_url: String,
api_key: String,
http: hpx::Client,
}
impl std::fmt::Debug for ComplianceClient {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ComplianceClient")
.field("base_url", &self.base_url)
.field("api_key", &"<redacted>")
.finish_non_exhaustive()
}
}
impl ComplianceClient {
pub fn new(api_key: impl Into<String>) -> Self {
Self::with_base_url(api_key, "https://api.circle.com")
}
pub fn with_base_url(api_key: impl Into<String>, base_url: impl Into<String>) -> Self {
Self { base_url: base_url.into(), api_key: api_key.into(), http: hpx::Client::new() }
}
async fn post<T, B>(&self, path: &str, body: &B) -> Result<T, Error>
where
T: serde::de::DeserializeOwned,
B: serde::Serialize + ?Sized,
{
let url = format!("{}{}", self.base_url, path);
let resp = self
.http
.post(&url)
.header("Authorization", format!("Bearer {}", self.api_key))
.header("X-Request-Id", uuid::Uuid::new_v4().to_string())
.json(body)
.send()
.await
.map_err(|e| Error::Http(e.to_string()))?;
if resp.status().is_success() {
resp.json::<T>().await.map_err(|e| Error::Http(e.to_string()))
} else {
let err: ApiErrorBody = resp.json().await.map_err(|e| Error::Http(e.to_string()))?;
Err(Error::Api { code: err.code, message: err.message })
}
}
pub async fn screen_address(
&self,
req: &ScreenAddressRequest,
) -> Result<BlockchainAddressScreeningResponse, Error> {
let envelope: ScreenAddressEnvelope =
self.post("/v1/w3s/compliance/screening/addresses", req).await?;
Ok(envelope.data)
}
}