use crate::models::{is_public_key, Request};
use crate::paths::*;
use crate::BuildQueryParametersExt;
#[derive(Default, Clone, Debug)]
pub struct NoSource;
#[derive(Clone, Debug)]
pub enum Source {
SourceAssets(Vec<IssuedOrNative>),
SourceAccount(String),
}
impl Default for Source {
fn default() -> Self {
Source::SourceAssets(Vec::new())
}
}
#[derive(Default, Clone)]
pub struct ListStrictReceivePaymentPathsRequest<
DAs = NoDestinationAsset,
DAm = NoDestinationAmount,
S = Source,
> {
destination_asset: DAs,
destination_amount: DAm,
destination_account: Option<String>,
source: S,
}
impl ListStrictReceivePaymentPathsRequest<NoDestinationAsset, NoDestinationAmount, NoSource> {
pub fn new() -> Self {
ListStrictReceivePaymentPathsRequest {
destination_asset: NoDestinationAsset,
destination_amount: NoDestinationAmount,
destination_account: None,
source: NoSource,
}
}
}
impl<DAs, DAm, S> ListStrictReceivePaymentPathsRequest<DAs, DAm, S> {
pub fn set_destination_asset(
self,
destination_asset_type: AssetType,
) -> Result<ListStrictReceivePaymentPathsRequest<DestinationAsset, DAm, S>, String> {
Ok(ListStrictReceivePaymentPathsRequest {
destination_asset: DestinationAsset(destination_asset_type),
destination_amount: self.destination_amount,
destination_account: self.destination_account,
source: self.source,
})
}
pub fn set_destination_amount(
self,
destination_amount: impl Into<String>,
) -> Result<ListStrictReceivePaymentPathsRequest<DAs, DestinationAmount, S>, String> {
Ok(ListStrictReceivePaymentPathsRequest {
destination_asset: self.destination_asset,
destination_amount: DestinationAmount(destination_amount.into()),
destination_account: self.destination_account,
source: self.source,
})
}
pub fn set_source(
self,
source: Source,
) -> Result<ListStrictReceivePaymentPathsRequest<DAs, DAm, Source>, String> {
match &source {
Source::SourceAssets(assets) => {
if assets.is_empty() {
return Err("SourceAssets cannot be empty".to_string());
}
}
Source::SourceAccount(account) => {
if let Err(e) = is_public_key(&account) {
return Err(e.to_string());
}
}
}
Ok(ListStrictReceivePaymentPathsRequest {
destination_asset: self.destination_asset,
destination_amount: self.destination_amount,
destination_account: self.destination_account,
source: source,
})
}
}
impl ListStrictReceivePaymentPathsRequest<DestinationAsset, DestinationAmount, Source> {
pub fn set_destination_account(
self,
destination_account: impl Into<String>,
) -> Result<ListStrictReceivePaymentPathsRequest<DestinationAsset, DestinationAmount>, String>
{
let destination_account = destination_account.into();
if let Err(e) = is_public_key(&destination_account) {
return Err(e.to_string());
}
Ok(ListStrictReceivePaymentPathsRequest {
destination_asset: self.destination_asset,
destination_amount: self.destination_amount,
destination_account: Some(destination_account.into()),
source: self.source,
})
}
}
impl Request for ListStrictReceivePaymentPathsRequest<DestinationAsset, DestinationAmount, Source> {
fn get_query_parameters(&self) -> String {
let asset_type_prefix = "destination_asset_type=";
let asset_code_prefix = "&destination_asset_code=";
let asset_issuer_prefix = "&destination_asset_issuer=";
let destination_asset_parameters = match &self.destination_asset {
DestinationAsset(AssetType::Native) => format!("{}native", asset_type_prefix),
DestinationAsset(AssetType::Alphanumeric4(asset_data))
| DestinationAsset(AssetType::Alphanumeric12(asset_data)) => {
let asset_type = match self.destination_asset {
DestinationAsset(AssetType::Alphanumeric4(_)) => "credit_alphanum4",
DestinationAsset(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 source = match &self.source {
Source::SourceAssets(source_assets) => {
source_assets
.iter()
.enumerate()
.map(|(i, asset)| {
let prefix = if i == 0 { "source_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("")
}
Source::SourceAccount(account) => {
format!("source_account={}", account)
}
};
let query_parameters = vec![
Some(destination_asset_parameters),
Some(format!("destination_amount={}", self.destination_amount.0)),
self.destination_account
.as_ref()
.map(|d| format!("destination_account={}", d)),
Some(source),
];
query_parameters.build_query_parameters()
}
fn build_url(&self, base_url: &str) -> String {
format!(
"{}/{}/{}{}",
base_url,
super::PATHS_PATH,
super::PATHS_STRICT_RECEIVE_PATH,
self.get_query_parameters()
)
}
}