use serde::{Deserialize, Serialize};
use crate::client::Client;
use crate::error::Error;
use crate::models::transaction::{Transaction, TransactionFilter};
use crate::models::{AccountId, DateTime, TransactionId};
use crate::streaming::{
StreamConfig, StreamKind, TransactionKind, TransactionStream, stream_config_setters,
};
impl Client {
pub fn list_transactions(&self, account_id: impl Into<AccountId>) -> ListTransactionsRequest {
ListTransactionsRequest {
client: self.clone(),
account_id: account_id.into(),
params: Vec::new(),
}
}
pub async fn transaction(
&self,
account_id: impl Into<AccountId>,
transaction_id: impl Into<TransactionId>,
) -> Result<TransactionResponse, Error> {
let account_id = account_id.into();
let transaction_id = transaction_id.into();
self.execute(self.get(&[
"accounts",
account_id.as_str(),
"transactions",
transaction_id.as_str(),
]))
.await
}
pub fn transactions_id_range(
&self,
account_id: impl Into<AccountId>,
from: impl Into<TransactionId>,
to: impl Into<TransactionId>,
) -> TransactionsIdRangeRequest {
TransactionsIdRangeRequest {
client: self.clone(),
account_id: account_id.into(),
from: from.into(),
to: to.into(),
types: None,
}
}
pub fn transaction_stream(&self, account_id: impl Into<AccountId>) -> TransactionStreamRequest {
TransactionStreamRequest {
client: self.clone(),
account_id: account_id.into(),
config: StreamConfig::default(),
}
}
pub async fn transactions_since_id(
&self,
account_id: impl Into<AccountId>,
id: impl Into<TransactionId>,
) -> Result<TransactionsResponse, Error> {
let account_id = account_id.into();
let id = id.into();
let request = self
.get(&["accounts", account_id.as_str(), "transactions", "sinceid"])
.query(&[("id", id.as_str())]);
self.execute(request).await
}
}
#[derive(Debug)]
pub struct TransactionStreamRequest {
client: Client,
account_id: AccountId,
config: StreamConfig,
}
impl TransactionStreamRequest {
stream_config_setters!();
pub async fn send(self) -> Result<TransactionStream, Error> {
let mut kind = TransactionKind {
client: self.client,
account_id: self.account_id,
last_seen: None,
};
let initial = kind.connect(false).await?;
Ok(TransactionStream::new(kind, self.config, initial))
}
}
#[derive(Debug)]
pub struct ListTransactionsRequest {
client: Client,
account_id: AccountId,
params: Vec<(&'static str, String)>,
}
impl ListTransactionsRequest {
pub fn from(mut self, from: impl Into<DateTime>) -> Self {
self.params.push(("from", from.into().0));
self
}
pub fn to(mut self, to: impl Into<DateTime>) -> Self {
self.params.push(("to", to.into().0));
self
}
pub fn page_size(mut self, page_size: u32) -> Self {
self.params.push(("pageSize", page_size.to_string()));
self
}
pub fn types<I>(mut self, types: I) -> Self
where
I: IntoIterator<Item = TransactionFilter>,
{
let joined = types
.into_iter()
.map(|t| t.as_str().to_owned())
.collect::<Vec<_>>()
.join(",");
self.params.push(("type", joined));
self
}
pub async fn send(self) -> Result<ListTransactionsResponse, Error> {
let request = self
.client
.get(&["accounts", self.account_id.as_str(), "transactions"])
.query(&self.params);
self.client.execute(request).await
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ListTransactionsResponse {
#[serde(rename = "from", skip_serializing_if = "Option::is_none")]
pub from: Option<DateTime>,
#[serde(rename = "to", skip_serializing_if = "Option::is_none")]
pub to: Option<DateTime>,
#[serde(rename = "pageSize", skip_serializing_if = "Option::is_none")]
pub page_size: Option<i64>,
#[serde(rename = "type", default, skip_serializing_if = "Vec::is_empty")]
pub r#type: Vec<TransactionFilter>,
#[serde(rename = "count", skip_serializing_if = "Option::is_none")]
pub count: Option<i64>,
#[serde(rename = "pages", default, skip_serializing_if = "Vec::is_empty")]
pub pages: Vec<String>,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct TransactionResponse {
#[serde(rename = "transaction")]
pub transaction: Transaction,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}
#[derive(Debug)]
pub struct TransactionsIdRangeRequest {
client: Client,
account_id: AccountId,
from: TransactionId,
to: TransactionId,
types: Option<Vec<TransactionFilter>>,
}
impl TransactionsIdRangeRequest {
pub fn types<I>(mut self, types: I) -> Self
where
I: IntoIterator<Item = TransactionFilter>,
{
self.types = Some(types.into_iter().collect());
self
}
pub async fn send(self) -> Result<TransactionsResponse, Error> {
let mut request = self
.client
.get(&[
"accounts",
self.account_id.as_str(),
"transactions",
"idrange",
])
.query(&[("from", self.from.as_str()), ("to", self.to.as_str())]);
if let Some(types) = &self.types {
let joined = types
.iter()
.map(|t| t.as_str().to_owned())
.collect::<Vec<_>>()
.join(",");
request = request.query(&[("type", joined)]);
}
self.client.execute(request).await
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct TransactionsResponse {
#[serde(
rename = "transactions",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub transactions: Vec<Transaction>,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}