Skip to content

Commit

Permalink
[Remove Liquidity] Show ceres locked liquidity (#922)
Browse files Browse the repository at this point in the history
* show ceres locked liquidity percent

* change translation of locked

* refactoring rendering

* Update translations

Co-authored-by: Stefan Popov <17688105+stefashkaa@users.noreply.github.com>
Co-authored-by: Stefan Popov <stefanpopov@list.ru>
  • Loading branch information
3 people authored Jan 26, 2023
1 parent 6325528 commit 5338829
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@
"outputMessage": "Output is estimated. If the price changes more than {slippageTolerance}% your transaction will revert.",
"confirmTitle": "You will receive",
"shareOfPool": "Share of pool after transaction",
"locked": "{percent} deines Pools befinden sich im {lock}"
"locked": "{percent} of your pool is in {lock}"
},
"dexSettings": {
"title": "Settings",
Expand Down
2 changes: 1 addition & 1 deletion src/lang/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ export default {
'Output is estimated. If the price changes more than {slippageTolerance}% your transaction will revert.',
confirmTitle: 'You will receive',
shareOfPool: 'Share of pool after transaction',
locked: '{percent} of your pool is in staking',
locked: '{percent} of your pool is in {lock}',
},
tokens: {
symbol: 'Symbol',
Expand Down
15 changes: 15 additions & 0 deletions src/store/pool/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,25 @@ const actions = defineActions({
commit.setAccountLiquidityUpdates(liquidityUpdatedSubscription);
});
},
async subscribeOnAccountLockedLiquidity(context): Promise<void> {
const { commit, rootGetters } = poolActionContext(context);
commit.resetAccountLockedLiquidityUpdates();

if (!rootGetters.wallet.account.isLoggedIn) return;

await waitForAccountPair(() => {
const subscription = api.ceresLiquidityLocker.getLockerDataObservable().subscribe((data) => {
commit.setAccountLockedLiquidity(data);
});

commit.setAccountLockedLiquidityUpdates(subscription);
});
},
async unsubscribeAccountLiquidityListAndUpdates(context): Promise<void> {
const { commit } = poolActionContext(context);
commit.resetAccountLiquidityList();
commit.resetAccountLiquidityUpdates();
commit.resetAccountLockedLiquidityUpdates();
commit.resetAccountLiquidity();
commit.resetPoolApySubscription();
commit.resetPoolApyObject();
Expand Down
23 changes: 23 additions & 0 deletions src/store/pool/getters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { defineGetters } from 'direct-vuex';
import { FPNumber } from '@sora-substrate/math';

import { poolGetterContext } from './index';

import type { PoolState } from './types';

const getters = defineGetters<PoolState>()({
getLockedAmount(...args): (baseAsset: string, poolAsset: string) => FPNumber {
const { state } = poolGetterContext(args);

return (baseAsset: string, poolAsset: string) => {
return state.accountLockedLiquidity.reduce((value, accountLockedPool) => {
if (accountLockedPool.assetA === baseAsset && accountLockedPool.assetB === poolAsset) {
return value.add(accountLockedPool.poolTokens);
}
return value;
}, FPNumber.ZERO);
};
},
});

export default getters;
7 changes: 5 additions & 2 deletions src/store/pool/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import { defineModule } from 'direct-vuex';

import { localActionContext } from '@/store';
import { localActionContext, localGetterContext } from '@/store';
import { Module } from '@/store/consts';

import mutations from './mutations';
import state from './state';
import actions from './actions';
import getters from './getters';

const pool = defineModule({
namespaced: true,
state,
mutations,
actions,
getters,
});

const poolActionContext = (context: any) => localActionContext(context, Module.Pool, pool);
const poolGetterContext = (args: [any, any, any, any]) => localGetterContext(args, Module.Pool, pool);

export { poolActionContext };
export { poolActionContext, poolGetterContext };
export default pool;
11 changes: 11 additions & 0 deletions src/store/pool/mutations.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineMutations } from 'direct-vuex';
import type { Subscription } from 'rxjs';
import type { AccountLiquidity } from '@sora-substrate/util/build/poolXyk/types';
import type { AccountLockedPool } from '@sora-substrate/util/build/ceresLiquidityLocker/types';
import type { PoolApyObject } from '@soramitsu/soraneo-wallet-web/lib/services/subquery/types';

import type { PoolState } from './types';
Expand All @@ -26,6 +27,16 @@ const mutations = defineMutations<PoolState>()({
resetAccountLiquidity(state): void {
state.accountLiquidity = [];
},
setAccountLockedLiquidity(state, lockedLiquidity: AccountLockedPool[]): void {
state.accountLockedLiquidity = Object.freeze([...lockedLiquidity]); // update vuex state by creating new copy of array
},
setAccountLockedLiquidityUpdates(state, subscription: Subscription): void {
state.accountLockedLiquiditySubscription = subscription;
},
resetAccountLockedLiquidityUpdates(state): void {
state.accountLockedLiquiditySubscription?.unsubscribe();
state.accountLockedLiquiditySubscription = null;
},
setPoolApyObject(state, object: PoolApyObject): void {
state.poolApyObject = object;
},
Expand Down
2 changes: 2 additions & 0 deletions src/store/pool/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ function initialState(): PoolState {
accountLiquidityUpdates: null,
poolApyObject: {},
poolApySubscription: null,
accountLockedLiquidity: [],
accountLockedLiquiditySubscription: null,
};
}

Expand Down
3 changes: 3 additions & 0 deletions src/store/pool/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Subscription } from 'rxjs';
import type { AccountLiquidity } from '@sora-substrate/util/build/poolXyk/types';
import type { AccountLockedPool } from '@sora-substrate/util/build/ceresLiquidityLocker/types';
import type { PoolApyObject } from '@soramitsu/soraneo-wallet-web/lib/services/subquery/types';

export type PoolState = {
Expand All @@ -8,6 +9,8 @@ export type PoolState = {
accountLiquidityUpdates: Nullable<Subscription>;
poolApyObject: PoolApyObject;
poolApySubscription: Nullable<VoidFunction>;
accountLockedLiquidity: readonly AccountLockedPool[];
accountLockedLiquiditySubscription: Nullable<Subscription>;
};

export type LiquidityParams = {
Expand Down
28 changes: 23 additions & 5 deletions src/store/removeLiquidity/getters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,32 @@ const getters = defineGetters<RemoveLiquidityState>()({

return FPNumber.fromCodecValue(getters.liquidity.balance);
},
// Liquidity locked balance
liquidityBalanceLocked(...args): FPNumber {
// Liquidity locked balance in demeterFarmingPlatform
demeterLockedBalance(...args): FPNumber {
const { getters, rootGetters } = removeLiquidityGetterContext(args);

if (!rootGetters.demeterFarming || !getters.liquidity) return FPNumber.ZERO;
if (!getters.liquidity || !rootGetters.demeterFarming) return FPNumber.ZERO;

const baseAsset = getters.liquidity.firstAddress;
const poolAsset = getters.liquidity.secondAddress;
const balance = getters.liquidityBalanceFull;
const lockedBalance = rootGetters.demeterFarming.getLockedAmount(baseAsset, poolAsset, true);

const maxLocked = FPNumber.min(balance, lockedBalance) as FPNumber;

return maxLocked;
},
// Liquidity locked balance in demeterFarmingPlatform
ceresLockedBalance(...args): FPNumber {
const { getters, rootGetters } = removeLiquidityGetterContext(args);

if (!getters.liquidity) return FPNumber.ZERO;

const baseAsset = getters.liquidity.firstAddress;
const poolAsset = getters.liquidity.secondAddress;
const balance = getters.liquidityBalanceFull;
const lockedBalance = rootGetters.pool.getLockedAmount(baseAsset, poolAsset);

const maxLocked = FPNumber.min(balance, lockedBalance) as FPNumber;

return maxLocked;
Expand All @@ -58,9 +74,11 @@ const getters = defineGetters<RemoveLiquidityState>()({
const { getters } = removeLiquidityGetterContext(args);

const balance = getters.liquidityBalanceFull;
const lockedBalance = getters.liquidityBalanceLocked;
const demeterLockedBalance = getters.demeterLockedBalance;
const ceresLockedBalance = getters.ceresLockedBalance;
const maxLocked = FPNumber.max(demeterLockedBalance, ceresLockedBalance) as FPNumber;

return balance.sub(lockedBalance);
return balance.sub(maxLocked);
},
firstToken(...args): Nullable<RegisteredAccountAssetWithDecimals> {
const { getters, rootGetters } = removeLiquidityGetterContext(args);
Expand Down
8 changes: 7 additions & 1 deletion src/views/PoolContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@ import { action } from '@/store/decorators';
export default class PoolContainer extends Mixins(SubscriptionsMixin) {
@action.pool.subscribeOnAccountLiquidityList private subscribeOnList!: AsyncFnWithoutArgs;
@action.pool.subscribeOnAccountLiquidityUpdates private subscribeOnUpdates!: AsyncFnWithoutArgs;
@action.pool.subscribeOnAccountLockedLiquidity private subscribeOnLocked!: AsyncFnWithoutArgs;
@action.pool.unsubscribeAccountLiquidityListAndUpdates private unsubscribe!: AsyncFnWithoutArgs;
@action.pool.subscribeOnPoolsApy private subscribeOnPoolsApy!: AsyncFnWithoutArgs;
created(): void {
this.setStartSubscriptions([this.subscribeOnList, this.subscribeOnUpdates, this.subscribeOnPoolsApy]);
this.setStartSubscriptions([
this.subscribeOnList,
this.subscribeOnUpdates,
this.subscribeOnLocked,
this.subscribeOnPoolsApy,
]);
this.setResetSubscriptions([this.unsubscribe]);
}
}
Expand Down
51 changes: 36 additions & 15 deletions src/views/RemoveLiquidity.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
:show-tooltip="false"
@input="handleRemovePartChange"
/>
<div v-if="hasLockedPart" class="input-line input-line--footer locked-part">
{{ t('removeLiquidity.locked', { percent: liquidityBalanceLockedPercent }) }}
<div v-for="{ percent, lock } in locks" :key="lock" class="input-line input-line--footer locked-part">
<span class="locked-part-percent">{{ percent }}</span> {{ t('removeLiquidity.locked', { lock }) }}
</div>
</div>
</s-float-input>
Expand Down Expand Up @@ -134,7 +134,7 @@ import NetworkFeeDialogMixin from '@/components/mixins/NetworkFeeDialogMixin';
import router, { lazyComponent } from '@/router';
import { Components, PageNames } from '@/consts';
import { hasInsufficientXorForFee } from '@/utils';
import { hasInsufficientXorForFee, formatDecimalPlaces } from '@/utils';
import { getter, state, mutation, action } from '@/store/decorators';
import { FocusedField } from '@/store/removeLiquidity/types';
import type { LiquidityParams } from '@/store/pool/types';
Expand Down Expand Up @@ -170,6 +170,8 @@ export default class RemoveLiquidity extends Mixins(
@getter.assets.xor private xor!: Nullable<AccountAsset>;
@getter.removeLiquidity.liquidityBalanceFull private liquidityBalanceFull!: FPNumber;
@getter.removeLiquidity.liquidityBalance private liquidityBalance!: FPNumber;
@getter.removeLiquidity.demeterLockedBalance private demeterLockedBalance!: FPNumber;
@getter.removeLiquidity.ceresLockedBalance private ceresLockedBalance!: FPNumber;
@getter.removeLiquidity.liquidity liquidity!: AccountLiquidity;
@getter.removeLiquidity.firstToken firstToken!: Asset;
@getter.removeLiquidity.secondToken secondToken!: Asset;
Expand Down Expand Up @@ -258,18 +260,26 @@ export default class RemoveLiquidity extends Mixins(
return this.liquidityBalance.isZero();
}
get hasLockedPart(): boolean {
return FPNumber.isLessThan(this.liquidityBalance, this.liquidityBalanceFull);
}
get locks(): { percent: string; lock: string }[] {
return [
{
balance: this.demeterLockedBalance,
lock: 'Demeter Farming',
},
{
balance: this.ceresLockedBalance,
lock: 'Ceres Liquidity Locker',
},
].reduce<{ percent: string; lock: string }[]>((buffer, { balance, lock }) => {
if (!balance.isZero()) {
buffer.push({
lock,
percent: this.getLockedPercent(balance),
});
}
get liquidityBalanceLockedPercent() {
return (
this.liquidityBalanceFull
.sub(this.liquidityBalance)
.div(this.liquidityBalanceFull)
.mul(FPNumber.HUNDRED)
.toLocaleString() + '%'
);
return buffer;
}, []);
}
get isInsufficientBalance(): boolean {
Expand Down Expand Up @@ -317,7 +327,7 @@ export default class RemoveLiquidity extends Mixins(
}
get isMaxButtonAvailable(): boolean {
return Number(this.removePart) !== this.MAX_PART;
return !this.liquidityLocked && Number(this.removePart) !== this.MAX_PART;
}
handleRemovePartChange(value: string | number): void {
Expand All @@ -337,6 +347,12 @@ export default class RemoveLiquidity extends Mixins(
return tokenBalance.toString();
}
getLockedPercent(lockedBalance: FPNumber): string {
const percent = lockedBalance.div(this.liquidityBalanceFull).mul(FPNumber.HUNDRED);
return formatDecimalPlaces(percent, true);
}
async handleTokenChange(value: string, setValue: (v: any) => Promise<any>): Promise<any> {
await setValue(value);
}
Expand Down Expand Up @@ -399,6 +415,11 @@ export default class RemoveLiquidity extends Mixins(
.locked-part {
color: var(--s-color-base-content-secondary);
text-transform: uppercase;
justify-content: flex-start;
&-percent {
width: 50px;
}
}
</style>

Expand Down

0 comments on commit 5338829

Please sign in to comment.