abstract_std/objects/entry/
lp_token.rsuse std::fmt::Display;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{
constants::{ASSET_DELIMITER, TYPE_DELIMITER},
objects::AssetEntry,
};
pub type DexName = String;
#[derive(
Deserialize, Serialize, Clone, Debug, PartialEq, Eq, JsonSchema, PartialOrd, Ord, Default,
)]
pub struct LpToken {
pub dex: DexName,
pub assets: Vec<AssetEntry>,
}
impl LpToken {
pub fn new<T: ToString, U: Into<AssetEntry> + Clone>(dex_name: T, assets: Vec<U>) -> Self {
let mut assets = assets
.into_iter()
.map(|a| a.into())
.collect::<Vec<AssetEntry>>();
assets.sort_unstable();
Self {
dex: dex_name.to_string(),
assets,
}
}
}
impl Display for LpToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let assets = self
.assets
.iter()
.map(|a| a.as_str())
.collect::<Vec<&str>>()
.join(ASSET_DELIMITER);
write!(f, "{}{}{}", self.dex, TYPE_DELIMITER, assets)
}
}
#[cfg(test)]
mod test {
#![allow(clippy::needless_borrows_for_generic_args)]
use super::*;
mod implementation {
use super::*;
#[coverage_helper::test]
fn new_works() {
let dex_name = "junoswap";
let mut assets = vec![AssetEntry::from("junox"), AssetEntry::from("crab")];
let actual = LpToken::new(dex_name, assets.clone());
assets.sort();
let expected = LpToken {
dex: dex_name.to_string(),
assets,
};
assert_eq!(actual, expected);
}
#[coverage_helper::test]
fn assets_returns_asset_entries() {
let dex_name = "junoswap";
let assets = vec![AssetEntry::from("crab"), AssetEntry::from("junox")];
let lp_token = LpToken::new(dex_name, assets);
let expected = vec![AssetEntry::from("crab"), AssetEntry::from("junox")];
assert_eq!(lp_token.assets, expected);
}
}
mod from_asset_entry {
use super::*;
use crate::objects::AnsEntryConvertor;
#[coverage_helper::test]
fn test_from_asset_entry() {
let asset = AssetEntry::new("junoswap/crab,junox");
let lp_token = AnsEntryConvertor::new(asset).lp_token().unwrap();
assert_eq!(lp_token.dex, "junoswap".to_string());
assert_eq!(
lp_token.assets,
vec![AssetEntry::from("crab"), AssetEntry::from("junox")]
);
}
#[coverage_helper::test]
fn test_from_invalid_asset_entry() {
let asset = AssetEntry::new("junoswap/");
let lp_token = AnsEntryConvertor::new(asset).lp_token();
assert!(lp_token.is_err());
}
#[coverage_helper::test]
fn test_fewer_than_two_assets() {
let asset = AssetEntry::new("junoswap/crab");
let lp_token = AnsEntryConvertor::new(asset).lp_token();
assert!(lp_token.is_err());
}
}
mod into_asset_entry {
use super::*;
use crate::objects::AnsEntryConvertor;
#[coverage_helper::test]
fn into_asset_entry_works() {
let lp_token = LpToken::new("junoswap", vec!["crab".to_string(), "junox".to_string()]);
let expected = AssetEntry::new("junoswap/crab,junox");
assert_eq!(AnsEntryConvertor::new(lp_token).asset_entry(), expected);
}
}
mod from_pool_metadata {
use super::*;
use crate::objects::{AnsEntryConvertor, PoolMetadata, PoolType};
#[coverage_helper::test]
fn test_from_pool_metadata() {
let assets: Vec<AssetEntry> = vec!["crab".into(), "junox".into()];
let dex = "junoswap".to_string();
let pool = PoolMetadata {
dex: dex.clone(),
pool_type: PoolType::Stable,
assets: assets.clone(),
};
let lp_token = AnsEntryConvertor::new(pool).lp_token();
assert_eq!(lp_token.dex, dex);
assert_eq!(lp_token.assets, assets);
}
}
}