Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring pools rendering #890

Merged
merged 20 commits into from
Dec 20, 2022
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/components/App/Menu/AppMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
text-color="var(--s-color-base-content-primary)"
:active-text-color="mainMenuActiveColor"
active-hover-color="transparent"
:default-active="getCurrentPath()"
:default-active="currentPath"
@select="onSelect"
>
<s-menu-item-group v-for="(item, index) in sidebarMenuItems" :key="index">
Expand Down Expand Up @@ -130,7 +130,7 @@ export default class AppMenu extends Mixins(TranslationMixin) {
return SidebarMenuGroups.filter((menuItem) => menuItem.title !== PageNames.SoraCard);
}

getCurrentPath(): string {
get currentPath(): string {
if (PoolChildPages.includes(router.currentRoute.name as PageNames)) {
return PageNames.Pool;
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Pool/PoolInfo.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<template>
<template functional>
<div class="pool-info">
<slot name="prepend" />

Expand Down
112 changes: 57 additions & 55 deletions src/components/Swap/Chart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
import dayjs from 'dayjs';
import isEqual from 'lodash/fp/isEqual';
import { graphic } from 'echarts';
import { Component, Mixins, Watch } from 'vue-property-decorator';
import { Component, Mixins, Watch, Prop } from 'vue-property-decorator';
import { FPNumber } from '@sora-substrate/util';
import { SSkeleton, SSkeletonItem } from '@soramitsu/soramitsu-js-ui/lib/components/Skeleton';

Expand All @@ -109,11 +109,10 @@ import CandleIcon from '@/assets/img/charts/candle.svg?inline';

import { lazyComponent } from '@/router';
import { Components } from '@/consts';
import { getter } from '@/store/decorators';
import { debouncedInputHandler, getTextWidth, calcPriceChange } from '@/utils';
import { debouncedInputHandler, getTextWidth, calcPriceChange, formatDecimalPlaces } from '@/utils';
import { AssetSnapshot } from '@soramitsu/soraneo-wallet-web/lib/services/subquery/types';

import type { AccountAsset, Asset } from '@sora-substrate/util/build/assets/types';
import type { AccountAsset } from '@sora-substrate/util/build/assets/types';

type ChartDataItem = {
timestamp: number;
Expand Down Expand Up @@ -237,6 +236,21 @@ const AXIS_OFFSET = 8;

const SYNC_INTERVAL = 6 * 1000;

const signific =
(value: FPNumber) =>
(positive: string, negative: string, zero: string): string => {
return FPNumber.gt(value, FPNumber.ZERO) ? positive : FPNumber.lt(value, FPNumber.ZERO) ? negative : zero;
};

const formatChange = (value: FPNumber): string => {
const sign = signific(value)('+', '', '');
const priceChange = formatDecimalPlaces(value, true);

return `${sign}${priceChange}`;
};

const formatPrice = (value: number, symbol: string) => `${new FPNumber(value).toLocaleString()} ${symbol}`;

@Component({
components: {
TokenLogo: components.TokenLogo,
Expand All @@ -256,9 +270,9 @@ export default class SwapChart extends Mixins(
mixins.NumberFormatterMixin,
mixins.FormattedAmountMixin
) {
@getter.swap.tokenFrom tokenFrom!: AccountAsset;
@getter.swap.tokenTo tokenTo!: AccountAsset;
@getter.swap.isAvailable isAvailable!: boolean;
@Prop({ default: () => null, type: Object }) readonly tokenFrom!: Nullable<AccountAsset>;
@Prop({ default: () => null, type: Object }) readonly tokenTo!: Nullable<AccountAsset>;
@Prop({ default: false, type: Boolean }) readonly isAvailable!: boolean;

@Watch('tokenFrom')
@Watch('tokenTo')
Expand All @@ -272,21 +286,21 @@ export default class SwapChart extends Mixins(
readonly FontWeightRate = WALLET_CONSTS.FontWeightRate;

// ordered by timestamp DESC
prices: ChartDataItem[] = [];
pageInfos: Partial<SUBQUERY_TYPES.PageInfo>[] = [];
zoomStart = 0; // percentage of zoom start position
zoomEnd = 100; // percentage of zoom end position
precision = 2;
limits = {
private prices: ChartDataItem[] = [];
private pageInfos: Partial<SUBQUERY_TYPES.PageInfo>[] = [];
private zoomStart = 0; // percentage of zoom start position
private zoomEnd = 100; // percentage of zoom end position
private precision = 2;
private limits = {
min: Infinity,
max: 0,
};

updatePrices = debouncedInputHandler(this.getHistoricalPrices, 250, { leading: false });
forceUpdatePrices = debouncedInputHandler(this.resetAndUpdatePrices, 250, { leading: false });

priceUpdateWatcher: Nullable<FnWithoutArgs> = null;
priceUpdateTimestampSync: Nullable<NodeJS.Timer | number> = null;
private forceUpdatePrices = debouncedInputHandler(this.resetAndUpdatePrices, 250, { leading: false });
private priceUpdateRequestId = 0;
private priceUpdateWatcher: Nullable<FnWithoutArgs> = null;
private priceUpdateTimestampSync: Nullable<NodeJS.Timer | number> = null;

chartType: CHART_TYPES = CHART_TYPES.LINE;
selectedFilter: ChartFilter = LINE_CHART_FILTERS[0];
Expand All @@ -311,8 +325,8 @@ export default class SwapChart extends Mixins(
return this.tokenTo?.symbol ?? 'USD';
}

get tokens(): Asset[] {
return [this.tokenFrom, this.tokenTo].filter((token) => !!token);
get tokens(): AccountAsset[] {
return [this.tokenFrom, this.tokenTo].filter((token) => !!token) as AccountAsset[];
}

get tokensAddresses(): string[] {
Expand Down Expand Up @@ -537,17 +551,7 @@ export default class SwapChart extends Mixins(
formatter: (params) => {
const { data, seriesType } = params[0];

const signific = (value: FPNumber) => (positive: string, negative: string, zero: string) =>
FPNumber.gt(value, FPNumber.ZERO) ? positive : FPNumber.lt(value, FPNumber.ZERO) ? negative : zero;
const formatPrice = (value: number) => `${new FPNumber(value).toLocaleString()} ${this.symbol}`;
const formatChange = (value: FPNumber) => {
const sign = signific(value)('+', '', '');
const priceChange = this.formatPriceChange(value);

return `${sign}${priceChange}%`;
};

if (seriesType === CHART_TYPES.LINE) return formatPrice(data[1]);
if (seriesType === CHART_TYPES.LINE) return formatPrice(data[1], this.symbol);

if (seriesType === CHART_TYPES.CANDLE) {
const [timestamp, open, close, low, high] = data;
Expand All @@ -559,10 +563,10 @@ export default class SwapChart extends Mixins(
);

const rows = [
{ title: 'Open', data: formatPrice(open) },
{ title: 'High', data: formatPrice(high) },
{ title: 'Low', data: formatPrice(low) },
{ title: 'Close', data: formatPrice(close) },
{ title: 'Open', data: formatPrice(open, this.symbol) },
{ title: 'High', data: formatPrice(high, this.symbol) },
{ title: 'Low', data: formatPrice(low, this.symbol) },
{ title: 'Close', data: formatPrice(close, this.symbol) },
{ title: 'Change', data: formatChange(change), color: changeColor },
];

Expand Down Expand Up @@ -721,7 +725,7 @@ export default class SwapChart extends Mixins(
return Math.max(this.getPrecision(min), this.getPrecision(max));
}

private getHistoricalPrices(resetChartData = false): void {
private async getHistoricalPrices(resetChartData = false): Promise<void> {
if (resetChartData) {
this.clearData();
} else if (this.loading || this.isAllHistoricalPricesFetched(this.pageInfos)) {
Expand All @@ -732,26 +736,28 @@ export default class SwapChart extends Mixins(
if (this.tokensAddresses.length === 2 && !this.isAvailable) return;

const addresses = [...this.tokensAddresses];
const requestId = Date.now();

this.withApi(async () => {
await this.withLoading(async () => {
try {
const response = await this.getChartData(addresses, this.selectedFilter, this.pageInfos);
this.priceUpdateRequestId = requestId;

// if no response, or tokens were changed, return
if (!response || !isEqual(addresses)(this.tokensAddresses)) return;
await this.withApi(async () => {
try {
const response = await this.getChartData(addresses, this.selectedFilter, this.pageInfos);

this.limits = response.limits;
this.pageInfos = response.pageInfos;
this.precision = response.precision;
this.prices = [...this.prices, ...response.prices];
// if no response, or tokens were changed, return
if (!(response && isEqual(addresses)(this.tokensAddresses) && isEqual(requestId)(this.priceUpdateRequestId)))
return;

this.isFetchingError = false;
} catch (error) {
this.isFetchingError = true;
console.error(error);
}
});
this.limits = response.limits;
this.pageInfos = response.pageInfos;
this.precision = response.precision;
this.prices = [...this.prices, ...response.prices];

this.isFetchingError = false;
} catch (error) {
this.isFetchingError = true;
console.error(error);
}
});
}

Expand Down Expand Up @@ -919,10 +925,6 @@ export default class SwapChart extends Mixins(
private isAllHistoricalPricesFetched(pageInfos: Partial<SUBQUERY_TYPES.PageInfo>[]): boolean {
return pageInfos.some((pageInfo) => !pageInfo.hasNextPage);
}

private formatPriceChange(value: FPNumber): string {
return new FPNumber(value.toFixed(2)).toLocaleString();
}
}
</script>

Expand Down
2 changes: 1 addition & 1 deletion src/components/Swap/StatusActionBadge.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<template>
<template functional>
<s-card shadow="always" size="small" class="status-action-badge">
<span class="status-action-badge__label"><slot name="label" /></span>
<span class="status-action-badge__value"><slot name="value" /></span>
Expand Down
4 changes: 2 additions & 2 deletions src/components/mixins/SubscriptionsMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default class SubscriptionsMixin extends Mixins(mixins.LoadingMixin) {
@getter.settings.nodeIsConnected nodeIsConnected!: boolean;

startSubscriptionsList: Array<AsyncFnWithoutArgs> = [];
resetSubscriptionsList: Array<AsyncFnWithoutArgs> = [];
resetSubscriptionsList: Array<FnWithoutArgs> = [];

@Watch('isLoggedIn')
@Watch('nodeIsConnected')
Expand Down Expand Up @@ -37,7 +37,7 @@ export default class SubscriptionsMixin extends Mixins(mixins.LoadingMixin) {
this.startSubscriptionsList = list;
}

public setResetSubscriptions(list: AsyncFnWithoutArgs[]) {
public setResetSubscriptions(list: FnWithoutArgs[]) {
this.resetSubscriptionsList = list;
}

Expand Down
43 changes: 31 additions & 12 deletions src/modules/demeterFarming/components/CalculatorDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@
<s-row v-if="poolAsset" flex align="middle">
<pair-token-logo
v-if="isFarm && baseAsset"
key="pair"
:first-token="baseAsset"
:second-token="poolAsset"
class="title-logo"
/>
<token-logo v-else :token="poolAsset" class="title-logo" />
<token-logo v-else key="token" :token="poolAsset" class="title-logo" />
<span class="calculator-dialog-title">
<template v-if="isFarm">{{ baseAsset.symbol }}-</template>{{ poolAsset.symbol }}
</span>
</s-row>

<s-form class="el-form--actions" :show-message="false">
<template v-if="isFarm">
<template v-if="isFarm && baseAsset">
<token-input
v-if="baseAsset"
:balance="baseAssetBalance.toCodecString()"
:is-max-available="isBaseAssetMaxButtonAvailable"
:title="t('demeterFarming.amountAdd')"
Expand All @@ -27,7 +27,7 @@
@max="handleBaseAssetMax"
/>

<s-icon v-if="baseAsset && poolAsset" class="icon-divider" name="plus-16" />
<s-icon v-if="poolAsset" class="icon-divider" name="plus-16" />
</template>

<token-input
Expand Down Expand Up @@ -64,16 +64,17 @@
</template>

<script lang="ts">
import { Component, Mixins, Watch } from 'vue-property-decorator';
import { components } from '@soramitsu/soraneo-wallet-web';
import { FPNumber } from '@sora-substrate/util';
import { Component, Mixins, Watch, Prop } from 'vue-property-decorator';
import { components, mixins } from '@soramitsu/soraneo-wallet-web';
import { FPNumber, Operation } from '@sora-substrate/util';
import type { CodecString } from '@sora-substrate/util';
import type { AccountAsset } from '@sora-substrate/util/build/assets/types';

import StakeDialogMixin from '../mixins/StakeDialogMixin';
import PoolCardMixin from '../mixins/PoolCardMixin';

import { lazyComponent } from '@/router';
import { Components, Links } from '@/consts';
import { isMaxButtonAvailable, getMaxValue } from '@/utils';
import { getAssetBalance, isMaxButtonAvailable, getMaxValue, formatDecimalPlaces } from '@/utils';

@Component({
components: {
Expand All @@ -84,7 +85,9 @@ import { isMaxButtonAvailable, getMaxValue } from '@/utils';
TokenLogo: components.TokenLogo,
},
})
export default class CalculatorDialog extends Mixins(StakeDialogMixin) {
export default class CalculatorDialog extends Mixins(PoolCardMixin, mixins.DialogMixin, mixins.LoadingMixin) {
@Prop({ default: () => FPNumber.ZERO, type: Object }) readonly emission!: FPNumber;

@Watch('visible')
private resetValue() {
this.baseAssetValue = '';
Expand All @@ -100,12 +103,26 @@ export default class CalculatorDialog extends Mixins(StakeDialogMixin) {

readonly link = Links.demeterFarmingPlatform;

get networkFee(): CodecString {
return this.networkFees[Operation.DemeterFarmingDepositLiquidity];
}

get selectedPeriod(): string {
return String(this.interval);
}

get rewardsText(): string {
return `${this.rewardAssetSymbol} rewards`;
return this.t('demeterFarming.rewards', { symbol: this.rewardAssetSymbol });
}

get baseAssetDecimals(): number {
return this.baseAsset?.decimals ?? FPNumber.DEFAULT_PRECISION;
}

get baseAssetBalance(): FPNumber {
if (!this.baseAsset) return FPNumber.ZERO;

return FPNumber.fromCodecValue(getAssetBalance(this.baseAsset) ?? 0, this.baseAssetDecimals);
}

get isBaseAssetMaxButtonAvailable(): boolean {
Expand Down Expand Up @@ -153,6 +170,8 @@ export default class CalculatorDialog extends Mixins(StakeDialogMixin) {
}

get calculatedRewardsFiat(): Nullable<string> {
if (!this.rewardAsset) return null;

return this.getFiatAmountByFPNumber(this.calculatedRewards, this.rewardAsset as AccountAsset);
}

Expand All @@ -178,7 +197,7 @@ export default class CalculatorDialog extends Mixins(StakeDialogMixin) {
}

get calculatedRoiPercentFormatted(): string {
return new FPNumber(this.calculatedRoiPercent.toFixed(2)).toLocaleString() + '%';
return formatDecimalPlaces(this.calculatedRoiPercent, true);
}

selectPeriod(name: string): void {
Expand Down
4 changes: 2 additions & 2 deletions src/modules/demeterFarming/components/ClaimDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
import { Component, Mixins } from 'vue-property-decorator';
import { components, mixins, WALLET_CONSTS } from '@soramitsu/soraneo-wallet-web';

import AccountPoolMixin from '../mixins/AccountPoolMixin';
import PoolCardMixin from '../mixins/PoolCardMixin';
import TranslationMixin from '@/components/mixins/TranslationMixin';

@Component({
Expand All @@ -66,7 +66,7 @@ import TranslationMixin from '@/components/mixins/TranslationMixin';
},
})
export default class ClaimDialog extends Mixins(
AccountPoolMixin,
PoolCardMixin,
TranslationMixin,
mixins.DialogMixin,
mixins.LoadingMixin
Expand Down
Loading