use super::*;
use codec::{Decode, Encode, MaxEncodedLen};
use core::marker::PhantomData;
use scale_info::TypeInfo;
use sp_runtime::traits::TryConvert;
pub(super) type BalancePath<T> = Vec<(<T as Config>::AssetKind, <T as Config>::Balance)>;
pub type CreditOf<T> = Credit<<T as frame_system::Config>::AccountId, <T as Config>::Assets>;
#[derive(Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)]
pub struct PoolInfo<PoolAssetId> {
pub lp_token: PoolAssetId,
}
pub trait PoolLocator<AccountId, AssetKind, PoolId> {
fn address(id: &PoolId) -> Result<AccountId, ()>;
fn pool_id(asset1: &AssetKind, asset2: &AssetKind) -> Result<PoolId, ()>;
fn pool_address(asset1: &AssetKind, asset2: &AssetKind) -> Result<AccountId, ()> {
if let Ok(id) = Self::pool_id(asset1, asset2) {
Self::address(&id)
} else {
Err(())
}
}
}
pub struct WithFirstAsset<FirstAsset, AccountId, AssetKind, AccountIdConverter>(
PhantomData<(FirstAsset, AccountId, AssetKind, AccountIdConverter)>,
);
impl<FirstAsset, AccountId, AssetKind, AccountIdConverter>
PoolLocator<AccountId, AssetKind, (AssetKind, AssetKind)>
for WithFirstAsset<FirstAsset, AccountId, AssetKind, AccountIdConverter>
where
AssetKind: Eq + Clone + Encode,
AccountId: Decode,
FirstAsset: Get<AssetKind>,
AccountIdConverter: for<'a> TryConvert<&'a (AssetKind, AssetKind), AccountId>,
{
fn pool_id(asset1: &AssetKind, asset2: &AssetKind) -> Result<(AssetKind, AssetKind), ()> {
if asset1 == asset2 {
return Err(());
}
let first = FirstAsset::get();
if first == *asset1 {
Ok((first, asset2.clone()))
} else if first == *asset2 {
Ok((first, asset1.clone()))
} else {
Err(())
}
}
fn address(id: &(AssetKind, AssetKind)) -> Result<AccountId, ()> {
AccountIdConverter::try_convert(id).map_err(|_| ())
}
}
pub struct Ascending<AccountId, AssetKind, AccountIdConverter>(
PhantomData<(AccountId, AssetKind, AccountIdConverter)>,
);
impl<AccountId, AssetKind, AccountIdConverter>
PoolLocator<AccountId, AssetKind, (AssetKind, AssetKind)>
for Ascending<AccountId, AssetKind, AccountIdConverter>
where
AssetKind: Ord + Clone + Encode,
AccountId: Decode,
AccountIdConverter: for<'a> TryConvert<&'a (AssetKind, AssetKind), AccountId>,
{
fn pool_id(asset1: &AssetKind, asset2: &AssetKind) -> Result<(AssetKind, AssetKind), ()> {
if asset1 > asset2 {
Ok((asset2.clone(), asset1.clone()))
} else if asset1 < asset2 {
Ok((asset1.clone(), asset2.clone()))
} else {
Err(())
}
}
fn address(id: &(AssetKind, AssetKind)) -> Result<AccountId, ()> {
AccountIdConverter::try_convert(id).map_err(|_| ())
}
}
pub struct Chain<First, Second>(PhantomData<(First, Second)>);
impl<First, Second, AccountId, AssetKind> PoolLocator<AccountId, AssetKind, (AssetKind, AssetKind)>
for Chain<First, Second>
where
First: PoolLocator<AccountId, AssetKind, (AssetKind, AssetKind)>,
Second: PoolLocator<AccountId, AssetKind, (AssetKind, AssetKind)>,
{
fn pool_id(asset1: &AssetKind, asset2: &AssetKind) -> Result<(AssetKind, AssetKind), ()> {
First::pool_id(asset1, asset2).or(Second::pool_id(asset1, asset2))
}
fn address(id: &(AssetKind, AssetKind)) -> Result<AccountId, ()> {
First::address(id).or(Second::address(id))
}
}
pub struct AccountIdConverter<Seed, PoolId>(PhantomData<(Seed, PoolId)>);
impl<Seed, PoolId, AccountId> TryConvert<&PoolId, AccountId> for AccountIdConverter<Seed, PoolId>
where
PoolId: Encode,
AccountId: Decode,
Seed: Get<PalletId>,
{
fn try_convert(id: &PoolId) -> Result<AccountId, &PoolId> {
sp_io::hashing::blake2_256(&Encode::encode(&(Seed::get(), id))[..])
.using_encoded(|e| Decode::decode(&mut TrailingZeroInput::new(e)).map_err(|_| id))
}
}
pub struct AccountIdConverterNoSeed<PoolId>(PhantomData<PoolId>);
impl<PoolId, AccountId> TryConvert<&PoolId, AccountId> for AccountIdConverterNoSeed<PoolId>
where
PoolId: Encode,
AccountId: Decode,
{
fn try_convert(id: &PoolId) -> Result<AccountId, &PoolId> {
sp_io::hashing::blake2_256(&Encode::encode(id)[..])
.using_encoded(|e| Decode::decode(&mut TrailingZeroInput::new(e)).map_err(|_| id))
}
}