use crate::models::{is_public_key, Request};
use crate::paths::*;
use crate::BuildQueryParametersExt;
#[derive(Default, Clone, Debug)]
pub struct NoSourceAsset;
#[derive(Default, Clone, Debug)]
pub struct SourceAsset(AssetType);
#[derive(Default, Clone, Debug)]
pub struct NoSourceAmount;
#[derive(Default, Clone, Debug)]
pub struct SourceAmount(String);
#[derive(Default, Clone, Debug)]
pub struct NoDestination;
#[derive(Clone, Debug)]
pub enum Destination {
DestinationAssets(Vec<IssuedOrNative>),
DestinationAccount(String),
}
impl Default for Destination {
fn default() -> Self {
Destination::DestinationAssets(Vec::new())
}
}
#[derive(Default, Clone)]
pub struct ListStrictSendPaymentPathsRequest<
SAs = NoSourceAsset,
SAm = NoSourceAmount,
D = Destination,
> {
source_asset: SAs,
source_amount: SAm,
destination: D,
}
impl ListStrictSendPaymentPathsRequest<NoSourceAsset, NoSourceAmount, NoDestination> {
pub fn new() -> Self {
ListStrictSendPaymentPathsRequest {
source_asset: NoSourceAsset,
source_amount: NoSourceAmount,
destination: NoDestination,
}
}
}
impl<SAs, SAm, D> ListStrictSendPaymentPathsRequest<SAs, SAm, D> {
pub fn set_source_asset(
self,
source_asset_type: AssetType,
) -> Result<ListStrictSendPaymentPathsRequest<SourceAsset, SAm, D>, String> {
Ok(ListStrictSendPaymentPathsRequest {
source_asset: SourceAsset(source_asset_type),
source_amount: self.source_amount,
destination: self.destination,
})
}
pub fn set_source_amount(
self,
source_amount: impl Into<String>,
) -> Result<ListStrictSendPaymentPathsRequest<SAs, SourceAmount, D>, String> {
Ok(ListStrictSendPaymentPathsRequest {
source_asset: self.source_asset,
source_amount: SourceAmount(source_amount.into()),
destination: self.destination,
})
}
pub fn set_destination(
self,
destination: Destination,
) -> Result<ListStrictSendPaymentPathsRequest<SAs, SAm, Destination>, String> {
match &destination {
Destination::DestinationAssets(assets) => {
if assets.is_empty() {
return Err("DestinationAssets cannot be empty".to_string());
}
}
Destination::DestinationAccount(account) => {
if let Err(e) = is_public_key(&account) {
return Err(e.to_string());
}
}
}
Ok(ListStrictSendPaymentPathsRequest {
source_asset: self.source_asset,
source_amount: self.source_amount,
destination: destination,
})
}
}
impl Request for ListStrictSendPaymentPathsRequest<SourceAsset, SourceAmount, Destination> {
fn get_query_parameters(&self) -> String {
let asset_type_prefix = "source_asset_type=";
let asset_code_prefix = "&source_asset_code=";
let asset_issuer_prefix = "&source_asset_issuer=";
let source_asset_parameters = match &self.source_asset {
SourceAsset(AssetType::Native) => format!("{}native", asset_type_prefix),
SourceAsset(AssetType::Alphanumeric4(asset_data))
| SourceAsset(AssetType::Alphanumeric12(asset_data)) => {
let asset_type = match self.source_asset {
SourceAsset(AssetType::Alphanumeric4(_)) => "credit_alphanum4",
SourceAsset(AssetType::Alphanumeric12(_)) => "credit_alphanum12",
_ => "", };
format!(
"{}{}{}{}{}{}",
asset_type_prefix,
asset_type,
asset_issuer_prefix,
asset_data.asset_issuer,
asset_code_prefix,
asset_data.asset_code,
)
}
};
let destination = match &self.destination {
Destination::DestinationAssets(destination_assets) => {
destination_assets
.iter()
.enumerate()
.map(|(i, asset)| {
let prefix = if i == 0 { "destination_assets=" } else { "%2C" };
match asset {
IssuedOrNative::Native => format!("{}native", prefix),
IssuedOrNative::Issued(asset_data) => {
format!(
"{}{}%3A{}",
prefix, asset_data.asset_code, asset_data.asset_issuer
)
}
}
})
.collect::<Vec<_>>()
.join("")
}
Destination::DestinationAccount(account) => {
format!("destination_account={}", account)
}
};
let query_parameters = vec![
Some(format!("source_amount={}", self.source_amount.0)),
Some(destination),
Some(source_asset_parameters),
];
query_parameters.build_query_parameters()
}
fn build_url(&self, base_url: &str) -> String {
format!(
"{}/{}/{}{}",
base_url,
super::PATHS_PATH,
super::PATHS_STRICT_SEND_PATH,
self.get_query_parameters()
)
}
}