Skip to content

Commit

Permalink
feat: auto sweep earnings and accurate free balance rpc (PRO-856) (#4145
Browse files Browse the repository at this point in the history
)

feat: auto sweep earnings and accurate free balance rpc
  • Loading branch information
AlastairHolmes committed Oct 23, 2023
1 parent c54d754 commit f9bf5e5
Show file tree
Hide file tree
Showing 8 changed files with 337 additions and 182 deletions.
16 changes: 10 additions & 6 deletions api/lib/src/lp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct RangeOrderReturn {

fn collect_range_order_returns(
events: impl IntoIterator<Item = state_chain_runtime::RuntimeEvent>,
order_id: OrderId,
) -> Vec<RangeOrderReturn> {
events
.into_iter()
Expand All @@ -40,9 +41,10 @@ fn collect_range_order_returns(
assets_delta,
collected_fees,
tick_range,
id,
..
},
) => Some(RangeOrderReturn {
) if order_id == id => Some(RangeOrderReturn {
liquidity_delta,
liquidity_total,
increase_or_decrease,
Expand All @@ -66,6 +68,7 @@ pub struct LimitOrderReturn {

fn collect_limit_order_returns(
events: impl IntoIterator<Item = state_chain_runtime::RuntimeEvent>,
order_id: OrderId,
) -> Vec<LimitOrderReturn> {
events
.into_iter()
Expand All @@ -77,9 +80,10 @@ fn collect_limit_order_returns(
collected_fees,
bought_amount,
tick,
id,
..
},
) => Some(LimitOrderReturn {
) if order_id == id => Some(LimitOrderReturn {
tick,
amount_total,
collected_fees,
Expand Down Expand Up @@ -177,7 +181,7 @@ pub trait LpApi: SignedExtrinsicApi {
.until_in_block()
.await?;

Ok(collect_range_order_returns(events))
Ok(collect_range_order_returns(events, id))
}

async fn set_range_order(
Expand All @@ -201,7 +205,7 @@ pub trait LpApi: SignedExtrinsicApi {
.until_in_block()
.await?;

Ok(collect_range_order_returns(events))
Ok(collect_range_order_returns(events, id))
}

async fn update_limit_order(
Expand All @@ -227,7 +231,7 @@ pub trait LpApi: SignedExtrinsicApi {
.until_in_block()
.await?;

Ok(collect_limit_order_returns(events))
Ok(collect_limit_order_returns(events, id))
}

async fn set_limit_order(
Expand All @@ -251,6 +255,6 @@ pub trait LpApi: SignedExtrinsicApi {
.until_in_block()
.await?;

Ok(collect_limit_order_returns(events))
Ok(collect_limit_order_returns(events, id))
}
}
5 changes: 4 additions & 1 deletion state-chain/pallets/cf-lp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use cf_chains::{address::AddressConverter, AnyChain, ForeignChainAddress};
use cf_primitives::{Asset, AssetAmount, ForeignChain};
use cf_traits::{
impl_pallet_safe_mode, liquidity::LpBalanceApi, AccountRoleRegistry, Chainflip, DepositApi,
EgressApi,
EgressApi, PoolApi,
};

#[cfg(feature = "try-runtime")]
Expand Down Expand Up @@ -59,6 +59,9 @@ pub mod pallet {
/// Safe Mode access.
type SafeMode: Get<PalletSafeMode>;

/// The interface for sweeping funds from pools into free balance
type PoolApi: PoolApi;

/// Benchmark weights
type WeightInfo: WeightInfo;
}
Expand Down
1 change: 1 addition & 0 deletions state-chain/pallets/cf-lp/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ impl crate::Config for Test {
type AddressConverter = MockAddressConverter;
type SafeMode = MockRuntimeSafeMode;
type WeightInfo = ();
type PoolApi = Self;
}

pub const LP_ACCOUNT: [u8; 32] = [1u8; 32];
Expand Down
248 changes: 138 additions & 110 deletions state-chain/pallets/cf-lp/src/weights.rs

Large diffs are not rendered by default.

70 changes: 69 additions & 1 deletion state-chain/pallets/cf-pools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use cf_amm::{
PoolState,
};
use cf_primitives::{chains::assets::any, Asset, AssetAmount, SwapOutput, STABLE_ASSET};
use cf_traits::{impl_pallet_safe_mode, Chainflip, LpBalanceApi, SwappingApi};
use cf_traits::{impl_pallet_safe_mode, Chainflip, LpBalanceApi, PoolApi, SwappingApi};
use frame_support::{
pallet_prelude::*,
sp_runtime::{Permill, Saturating},
Expand Down Expand Up @@ -669,6 +669,7 @@ pub mod pallet {
);
let lp = T::AccountRoleRegistry::ensure_liquidity_provider(origin)?;
T::LpBalance::ensure_has_refund_address_for_pair(&lp, base_asset, pair_asset)?;
Self::inner_sweep(&lp)?;
Self::try_mutate_enabled_pool(base_asset, pair_asset, |asset_pair, pool| {
let tick_range = match (
pool.range_orders_cache
Expand Down Expand Up @@ -753,6 +754,7 @@ pub mod pallet {
);
let lp = T::AccountRoleRegistry::ensure_liquidity_provider(origin)?;
T::LpBalance::ensure_has_refund_address_for_pair(&lp, base_asset, pair_asset)?;
Self::inner_sweep(&lp)?;
Self::try_mutate_enabled_pool(base_asset, pair_asset, |asset_pair, pool| {
let tick_range = match (
pool.range_orders_cache
Expand Down Expand Up @@ -826,6 +828,7 @@ pub mod pallet {
);
let lp = T::AccountRoleRegistry::ensure_liquidity_provider(origin)?;
T::LpBalance::ensure_has_refund_address_for_pair(&lp, sell_asset, buy_asset)?;
Self::inner_sweep(&lp)?;
Self::try_mutate_enabled_pool(sell_asset, buy_asset, |asset_pair, pool| {
let tick = match (
pool.limit_orders_cache[asset_pair.base_side]
Expand Down Expand Up @@ -902,6 +905,7 @@ pub mod pallet {
);
let lp = T::AccountRoleRegistry::ensure_liquidity_provider(origin)?;
T::LpBalance::ensure_has_refund_address_for_pair(&lp, sell_asset, buy_asset)?;
Self::inner_sweep(&lp)?;
Self::try_mutate_enabled_pool(sell_asset, buy_asset, |asset_pair, pool| {
let tick = match (
pool.limit_orders_cache[asset_pair.base_side]
Expand Down Expand Up @@ -1039,6 +1043,14 @@ impl<T: Config> SwappingApi for Pallet<T> {
}
}

impl<T: Config> PoolApi for Pallet<T> {
type AccountId = T::AccountId;

fn sweep(who: &T::AccountId) -> DispatchResult {
Self::inner_sweep(who)
}
}

impl<T: Config> cf_traits::FlipBurnInfo for Pallet<T> {
fn take_flip_to_burn() -> AssetAmount {
FlipToBurn::<T>::take()
Expand Down Expand Up @@ -1106,6 +1118,62 @@ pub struct UnidirectionalPoolDepth {
}

impl<T: Config> Pallet<T> {
fn inner_sweep(lp: &T::AccountId) -> DispatchResult {
// Collect to avoid undefined behaviour (See StorsgeMap::iter_keys documentation)
for canonical_asset_pair in Pools::<T>::iter_keys().collect::<Vec<_>>() {
let mut pool = Pools::<T>::get(canonical_asset_pair).unwrap();

if let Some(range_orders_cache) = pool.range_orders_cache.get(lp).cloned() {
let asset_pair = AssetPair { canonical_asset_pair, base_side: Side::Zero };

for (id, range) in range_orders_cache.iter() {
Self::inner_update_range_order(
&mut pool,
lp,
&asset_pair,
*id,
range.clone(),
IncreaseOrDecrease::Decrease,
range_orders::Size::Liquidity { liquidity: 0 },
false,
)?;
}
}

for (side, limit_orders_cache) in pool
.limit_orders_cache
.as_ref()
.into_iter()
.filter_map(|(side, limit_orders_cache)| {
limit_orders_cache
.get(lp)
.cloned()
.map(|limit_orders_cache| (side, limit_orders_cache))
})
.collect::<Vec<_>>()
{
let asset_pair = AssetPair { canonical_asset_pair, base_side: side };

for (id, tick) in limit_orders_cache {
Self::inner_update_limit_order(
&mut pool,
lp,
&asset_pair,
id,
tick,
IncreaseOrDecrease::Decrease,
Default::default(),
false,
)?;
}
}

Pools::<T>::insert(canonical_asset_pair, pool);
}

Ok(())
}

#[allow(clippy::too_many_arguments)]
fn inner_update_limit_order(
pool: &mut Pool<T>,
Expand Down
Loading

0 comments on commit f9bf5e5

Please sign in to comment.