Skip to content

Commit 84d010b

Browse files
committed
feat: best trade swap router rpc
Signed-off-by: Gregory Hill <[email protected]>
1 parent fdc136b commit 84d010b

File tree

30 files changed

+1079
-69
lines changed

30 files changed

+1079
-69
lines changed

Cargo.lock

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/dex-general/src/swap/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,13 @@ impl<T: Config> Pallet<T> {
976976
}
977977

978978
impl<T: Config> ExportDexGeneral<T::AccountId, T::AssetId> for Pallet<T> {
979+
fn get_all_trading_pairs() -> Vec<(T::AssetId, T::AssetId)> {
980+
PairStatuses::<T>::iter()
981+
.filter(|(_, status)| matches!(status, PairStatus::Trading(_)))
982+
.map(|(pair, _)| pair)
983+
.collect()
984+
}
985+
979986
fn get_amount_in_by_path(
980987
amount_out: AssetBalance,
981988
path: &[T::AssetId],
@@ -1052,6 +1059,10 @@ impl<T: Config> ExportDexGeneral<T::AccountId, T::AssetId> for Pallet<T> {
10521059
}
10531060

10541061
impl<AccountId, AssetId> ExportDexGeneral<AccountId, AssetId> for () {
1062+
fn get_all_trading_pairs() -> Vec<(AssetId, AssetId)> {
1063+
unimplemented!()
1064+
}
1065+
10551066
fn get_amount_in_by_path(_amount_out: AssetBalance, _path: &[AssetId]) -> Result<Vec<AssetBalance>, DispatchError> {
10561067
unimplemented!()
10571068
}

crates/dex-general/src/traits.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ pub trait GenerateLpAssetId<AssetId> {
88
}
99

1010
pub trait ExportDexGeneral<AccountId, AssetId> {
11+
fn get_all_trading_pairs() -> Vec<(AssetId, AssetId)>;
12+
1113
fn get_amount_in_by_path(amount_out: AssetBalance, path: &[AssetId]) -> Result<Vec<AssetBalance>, DispatchError>;
1214

1315
fn get_amount_out_by_path(amount_in: AssetBalance, path: &[AssetId]) -> Result<Vec<AssetBalance>, DispatchError>;

crates/dex-stable/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1410,7 +1410,7 @@ impl<T: Config> Pallet<T> {
14101410
) -> Result<Balance, DispatchError> {
14111411
let base_pool_currency = Self::get_lp_currency(base_pool_id).ok_or(Error::<T>::InvalidPoolId)?;
14121412
let base_pool_currency_index =
1413-
Self::get_currency_index(pool_id, base_pool_currency).ok_or(Error::<T>::InvalidBasePool)?;
1413+
Self::get_currency_index(pool_id, base_pool_currency).ok_or(Error::<T>::InvalidBasePool)? as u32;
14141414

14151415
let mut base_lp_amount = Balance::default();
14161416
if base_pool_currency_index != in_index {
@@ -1430,6 +1430,7 @@ impl<T: Config> Pallet<T> {
14301430
Ok(out_amount)
14311431
}
14321432

1433+
/// Returns the amount of LP tokens generated by supplying the `amounts` in the pool.
14331434
pub(crate) fn calculate_currency_amount(
14341435
pool_id: T::PoolId,
14351436
amounts: Vec<Balance>,

crates/dex-stable/src/meta_pool_tests.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4348,3 +4348,79 @@ fn meta_pool_swap_underlying_impact_on_base_pool_price_should_work() {
43484348
);
43494349
})
43504350
}
4351+
4352+
// TODO: rewrite to use mock values
4353+
fn calculate_swap(pool_id: PoolId, i: usize, j: usize, in_balance: Balance) -> Balance {
4354+
let pool = StableAmm::pools(pool_id).unwrap().get_pool_info();
4355+
let normalized_balances = StableAmm::xp(&pool.balances, &pool.token_multipliers).unwrap();
4356+
let new_in_balance = normalized_balances[i] + in_balance * pool.token_multipliers[i];
4357+
let out_balance = StableAmm::get_y(&pool, i, j, new_in_balance, &normalized_balances).unwrap();
4358+
let out_amount = (normalized_balances[j] - out_balance) / pool.token_multipliers[j];
4359+
let fee = (out_amount * pool.fee) / FEE_DENOMINATOR;
4360+
out_amount - fee
4361+
}
4362+
4363+
#[test]
4364+
fn should_calculate_swap_amount_from_base() {
4365+
new_test_ext().execute_with(|| {
4366+
// asset 0 (base): 1e20 + 1e20 + 1e20
4367+
// asset 1 (base): 1e8 + 1e8 + 1e8
4368+
// asset 2 (base): 1e8 + 1e8 + 1e8
4369+
// asset 0 (meta): 1e18
4370+
// asset 1 (meta): 1e18
4371+
let (base_pool_id, meta_pool_id) = setup_test_meta_pool();
4372+
4373+
fn calculate_token_amount(pool_id: PoolId, amounts: &Vec<Balance>, deposit: bool) -> Balance {
4374+
let pool = StableAmm::pools(pool_id).unwrap().get_pool_info();
4375+
let amp = pool.future_a;
4376+
let d0 = StableAmm::xp(&pool.balances, &pool.token_multipliers)
4377+
.and_then(|xp| StableAmm::get_d(&xp, amp))
4378+
.unwrap();
4379+
let new_balances = pool
4380+
.balances
4381+
.iter()
4382+
.zip(amounts.iter())
4383+
.map(|(x, y)| if deposit { x + y } else { x - y })
4384+
.collect::<Vec<_>>();
4385+
let d1 = StableAmm::xp(&new_balances, &pool.token_multipliers)
4386+
.and_then(|xp| StableAmm::get_d(&xp, amp))
4387+
.unwrap();
4388+
let total_supply = <Test as Config>::MultiCurrency::total_issuance(pool.lp_currency_id);
4389+
let diff = if deposit { d1 - d0 } else { d0 - d1 };
4390+
(diff * total_supply) / d0
4391+
}
4392+
4393+
let swap_amount = 100_000;
4394+
let mut base_amounts = vec![0; 3];
4395+
base_amounts[0] = swap_amount;
4396+
let base_lp_amount = calculate_token_amount(base_pool_id, &base_amounts, true);
4397+
assert_ok!(
4398+
StableAmm::stable_amm_calculate_currency_amount(base_pool_id, &base_amounts, true),
4399+
base_lp_amount
4400+
);
4401+
4402+
assert_eq!(
4403+
StableAmm::stable_amm_calculate_swap_amount_from_base(meta_pool_id, base_pool_id, 0, 0, swap_amount)
4404+
.unwrap()
4405+
.unwrap(),
4406+
calculate_swap(meta_pool_id, 0, 1, base_lp_amount),
4407+
);
4408+
})
4409+
}
4410+
4411+
#[test]
4412+
fn should_calculate_swap_amount_to_base() {
4413+
new_test_ext().execute_with(|| {
4414+
let (base_pool_id, meta_pool_id) = setup_test_meta_pool();
4415+
let base_pool = StableAmm::pools(base_pool_id).unwrap().get_pool_info();
4416+
let token_lp_amount = calculate_swap(meta_pool_id, 0, 1, 100_000);
4417+
assert_eq!(
4418+
StableAmm::stable_amm_calculate_swap_amount_to_base(meta_pool_id, base_pool_id, 0, 0, 100_000)
4419+
.unwrap()
4420+
.unwrap(),
4421+
StableAmm::calculate_base_remove_liquidity_one_token(&base_pool, token_lp_amount, 0)
4422+
.unwrap()
4423+
.0,
4424+
);
4425+
})
4426+
}

crates/dex-stable/src/primitives.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ pub enum Pool<PoolId, CurrencyId, AccountId, BoundString> {
7373
Meta(MetaPool<PoolId, CurrencyId, AccountId, BoundString>),
7474
}
7575

76-
impl<PoolId, CurrencyId: Copy, AccountId: Clone, BoundString> Pool<PoolId, CurrencyId, AccountId, BoundString> {
76+
impl<PoolId, CurrencyId: Copy + PartialEq, AccountId: Clone, BoundString>
77+
Pool<PoolId, CurrencyId, AccountId, BoundString>
78+
{
7779
pub fn info(self) -> BasePool<CurrencyId, AccountId, BoundString> {
7880
match self {
7981
Pool::Base(bp) => bp,
@@ -88,6 +90,10 @@ impl<PoolId, CurrencyId: Copy, AccountId: Clone, BoundString> Pool<PoolId, Curre
8890
}
8991
}
9092

93+
pub fn get_currency_index(self, currency_id: CurrencyId) -> Option<usize> {
94+
self.get_currency_ids().iter().position(|&r| r == currency_id)
95+
}
96+
9197
pub fn get_lp_currency(&self) -> CurrencyId {
9298
match self {
9399
Pool::Base(bp) => bp.lp_currency_id,

crates/dex-stable/src/rpc.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,12 @@ impl<T: Config> Pallet<T> {
4242
Vec::new()
4343
}
4444

45-
pub fn get_currency_index(pool_id: T::PoolId, currency_id: T::CurrencyId) -> Option<u32> {
45+
pub fn get_currency_index(pool_id: T::PoolId, currency_id: T::CurrencyId) -> Option<usize> {
4646
if let Some(pool) = Self::pools(pool_id) {
47-
for (i, c) in pool.get_currency_ids().iter().enumerate() {
48-
if *c == currency_id {
49-
return Some(i as u32);
50-
}
51-
}
52-
};
53-
None
47+
pool.get_currency_index(currency_id)
48+
} else {
49+
None
50+
}
5451
}
5552

5653
pub fn get_currency(pool_id: T::PoolId, index: u32) -> Option<T::CurrencyId> {

0 commit comments

Comments
 (0)