#![warn(missing_docs, clippy::pedantic)]
#![allow(clippy::module_name_repetitions, deprecated)]
#![doc = include_str!("../README.md")]
#[macro_use]
mod request;
pub mod methods;
pub mod responses;
pub mod user;
pub use crate::{responses::*, user::*};
use chrono::prelude::*;
use reqwest::Client;
use serde::Deserialize;
use std::fmt;
#[derive(Clone, Debug, Deserialize)]
pub struct CCashSessionProperties {
pub(crate) version: Option<u32>,
pub(crate) max_log: u32,
pub(crate) add_user_open: Option<bool>,
pub(crate) return_on_del: Option<String>,
}
impl CCashSessionProperties {
#[must_use]
pub fn get_version(&self) -> Option<u32> { self.version }
#[must_use]
pub fn get_max_log(&self) -> u32 { self.max_log }
#[must_use]
pub fn get_add_user_is_open(&self) -> bool {
let Some(b) = self.add_user_open else {
return true
};
b
}
#[must_use]
pub fn get_return_on_delete_account(&self) -> &Option<String> { &self.return_on_del }
}
#[derive(Debug, Deserialize)]
#[deprecated(since = "2.0.0", note = "Prefer the usage of `TransactionLogV2`")]
pub struct TransactionLog {
pub(crate) to: String,
pub(crate) from: String,
pub(crate) amount: u32,
pub(crate) time: i64,
}
impl TransactionLog {
#[must_use]
pub fn get_to_account(&self) -> &str { &self.to }
#[must_use]
pub fn get_from_account(&self) -> &str { &self.from }
#[must_use]
pub fn get_amount(&self) -> u32 { self.amount }
#[must_use]
pub fn get_time(&self) -> i64 { self.time }
}
impl fmt::Display for TransactionLog {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let time = DateTime::<Utc>::from_utc(
NaiveDateTime::from_timestamp_opt(self.time, 0).unwrap(),
Utc,
);
write!(
f,
"{}: {} ({} CSH) -> {}",
time, &self.from, self.amount, &self.to,
)
}
}
#[derive(Debug, Deserialize)]
pub struct TransactionLogV2 {
pub(crate) counterparty: String,
pub(crate) receiving: bool,
pub(crate) amount: u32,
pub(crate) time: i64,
}
impl TransactionLogV2 {
#[must_use]
pub fn get_counterparty(&self) -> &str { &self.counterparty }
#[must_use]
pub fn get_if_receiving(&self) -> bool { self.receiving }
#[must_use]
pub fn get_amount(&self) -> u32 { self.amount }
#[must_use]
pub fn get_time(&self) -> i64 { self.time }
}
impl fmt::Display for TransactionLogV2 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let action = if self.receiving { "Received" } else { "Sent" };
let tofrom = if self.receiving { "from" } else { "to" };
let time = DateTime::<Utc>::from_utc(
NaiveDateTime::from_timestamp_opt(self.time, 0).unwrap(),
Utc,
);
write!(
f,
"{time}: {action} {} CSH {tofrom} {}",
self.amount, self.counterparty
)
}
}
#[doc = include_str!("../examples/get_balance.rs")]
#[derive(Debug, Clone)]
pub struct CCashSession {
session_url: String,
is_connected: bool,
client: Option<Client>,
properties: Option<CCashSessionProperties>,
}
impl CCashSession {
#[must_use]
pub fn new(base_url: &str) -> CCashSession {
let base_url = if base_url.ends_with('/') {
base_url.trim_end_matches('/')
} else {
base_url
};
Self {
session_url: format!("{base_url}/api"),
is_connected: false,
client: None,
properties: None,
}
}
pub async fn establish_connection(&mut self) -> Result<()> {
if self.is_connected {
return Ok(());
}
let client = Client::builder().build()?;
let request = client
.get(format!("{}/properties", self.session_url))
.header("Accept", "application/json")
.build()?;
let response = client.execute(request).await?;
if let Ok(v) = response.json::<CCashSessionProperties>().await {
self.properties = Some(v);
self.is_connected = true;
self.client = Some(client);
Ok(())
} else {
Err(CCashError::CouldNotParsePropertiesResponse)
}
}
#[must_use]
pub fn get_client(&self) -> &Option<Client> { &self.client }
#[must_use]
pub fn is_connected(&self) -> bool { self.is_connected }
#[must_use]
pub fn get_properties(&self) -> &Option<CCashSessionProperties> { &self.properties }
}