Skip to content

Commit

Permalink
APR Calculator (#754)
Browse files Browse the repository at this point in the history
* merge b50b4a7

* refactoring AddLiquidity input fields

* update StakeDialog

* pass balance to TokenInput

* merge 07bcac7

* update Swap

* update ReferralBonding

* merge f50f6ce

* merge c55e6eb

* add demeter copyright

* fix ts erros

* update translations

* add TranslationConsts

* add ~ sign to rewards
  • Loading branch information
Nikita-Polyakov authored Jul 27, 2022
1 parent 202ea67 commit 7f02bad
Show file tree
Hide file tree
Showing 41 changed files with 841 additions and 726 deletions.
3 changes: 3 additions & 0 deletions src/assets/img/calculator/signs.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
174 changes: 174 additions & 0 deletions src/components/Input/TokenInput.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<template>
<s-float-input
class="s-input--token-value"
size="medium"
has-locale-string
v-bind="{
decimals,
delimiters,
max,
value,
...$attrs,
}"
v-on="$listeners"
>
<div slot="top" class="input-line">
<div class="input-title">
<span class="input-title--uppercase input-title--primary">{{ title }}</span>
<slot name="title-append" />
</div>
<div class="input-value">
<slot name="balance">
<template v-if="token">
<span class="input-value--uppercase">{{ t('balanceText') }}</span>
<formatted-amount-with-fiat-value
value-can-be-hidden
with-left-shift
value-class="input-value--primary"
:value="formattedBalance"
:fiat-value="formattedFiatBalance"
/>
</template>
</slot>
</div>
</div>
<div slot="right" class="s-flex el-buttons">
<s-button
v-if="isMaxAvailable"
class="el-button--max s-typography-button--small"
type="primary"
alternative
size="mini"
border-radius="mini"
@click.stop="handleMax"
>
{{ t('buttons.max') }}
</s-button>
<token-select-button
class="el-button--select-token"
:icon="selectTokenIcon"
:token="token"
@click.stop="handleSelectToken"
/>
</div>
<div slot="bottom" class="input-line input-line--footer">
<div class="s-flex">
<formatted-amount v-if="tokenPrice" is-fiat-value :value="fiatAmount" />
<slot name="fiat-amount-append" />
</div>

<token-address
v-if="token"
:name="token.name"
:symbol="token.symbol"
:address="token.address"
class="input-value"
/>
</div>
</s-float-input>
</template>

<script lang="ts">
import { Component, Mixins, ModelSync, Prop } from 'vue-property-decorator';
import { components, mixins } from '@soramitsu/soraneo-wallet-web';
import { FPNumber } from '@sora-substrate/util';
import TranslationMixin from '@/components/mixins/TranslationMixin';
import { lazyComponent } from '@/router';
import { Components, ZeroStringValue } from '@/consts';
import type { CodecString } from '@sora-substrate/util';
import type { AccountAsset } from '@sora-substrate/util/build/assets/types';
@Component({
components: {
TokenSelectButton: lazyComponent(Components.TokenSelectButton),
FormattedAmount: components.FormattedAmount,
FormattedAmountWithFiatValue: components.FormattedAmountWithFiatValue,
TokenAddress: components.TokenAddress,
},
})
export default class TokenInput extends Mixins(
mixins.NumberFormatterMixin,
mixins.FormattedAmountMixin,
TranslationMixin
) {
@Prop({ default: () => null, type: Object }) readonly token!: Nullable<AccountAsset>;
@Prop({ default: () => null, type: String }) readonly balance!: Nullable<CodecString>;
@Prop({ default: '', type: String }) readonly title!: string;
@Prop({ default: false, type: Boolean }) readonly isMaxAvailable!: boolean;
@Prop({ default: false, type: Boolean }) readonly isSelectAvailable!: boolean;
@ModelSync('value', 'input', { type: String })
readonly amount!: string;
readonly delimiters = FPNumber.DELIMITERS_CONFIG;
get address(): string {
return this.token?.address ?? '';
}
get decimals(): number {
return this.token?.decimals ?? FPNumber.DEFAULT_PRECISION;
}
get max(): string {
return this.getMax(this.address);
}
get selectTokenIcon(): Nullable<string> {
return this.isSelectAvailable ? 'chevron-down-rounded-16' : undefined;
}
get fpBalance(): FPNumber {
if (!this.token || !this.balance) return FPNumber.ZERO;
return FPNumber.fromCodecValue(this.balance, this.decimals);
}
get formattedBalance(): string {
return this.fpBalance.toLocaleString();
}
get formattedFiatBalance(): string {
if (!this.token || !this.balance) return ZeroStringValue;
const fpTokenPrice = FPNumber.fromCodecValue(this.tokenPrice ?? 0, this.decimals);
return this.fpBalance.mul(fpTokenPrice).toLocaleString();
}
get tokenPrice(): Nullable<CodecString> {
if (!this.token) return null;
return this.getAssetFiatPrice(this.token);
}
get fiatAmount(): Nullable<string> {
if (!this.token) return null;
return this.getFiatAmount(this.amount, this.token);
}
handleMax(): void {
this.$emit('max', this.token);
}
handleSelectToken(): void {
this.$emit('select');
}
}
</script>

<style lang="scss">
.s-input--token-value .el-input .el-input__inner {
@include text-ellipsis;
}
</style>

<style lang="scss" scoped>
.s-input--token-value {
@include buttons;
}
</style>
43 changes: 2 additions & 41 deletions src/components/mixins/TokenPairMixin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component, Mixins, Watch } from 'vue-property-decorator';
import { mixins } from '@soramitsu/soraneo-wallet-web';
import { CodecString, FPNumber } from '@sora-substrate/util';
import { CodecString } from '@sora-substrate/util';
import type { AccountAsset } from '@sora-substrate/util/build/assets/types';

import ConfirmDialogMixin from './ConfirmDialogMixin';
Expand All @@ -10,14 +10,7 @@ import TokenSelectMixin from './TokenSelectMixin';
import router from '@/router';
import { PageNames } from '@/consts';
import { state, getter, mutation, action } from '@/store/decorators';
import {
getMaxValue,
isMaxButtonAvailable,
isXorAccountAsset,
hasInsufficientBalance,
formatAssetBalance,
getAssetBalance,
} from '@/utils';
import { getMaxValue, isMaxButtonAvailable, isXorAccountAsset, hasInsufficientBalance, getAssetBalance } from '@/utils';
import type { PricesPayload } from '@/store/prices/types';

const TokenPairMixinInstance = (namespace: TokenPairNamespace) => {
Expand Down Expand Up @@ -104,34 +97,6 @@ const TokenPairMixinInstance = (namespace: TokenPairNamespace) => {
return false;
}

get firstTokenAddress(): string {
return this.firstToken?.address ?? '';
}

get secondTokenAddress(): string {
return this.secondToken?.address ?? '';
}

get firstTokenDecimals(): number {
return this.firstToken?.decimals ?? FPNumber.DEFAULT_PRECISION;
}

get secondTokenDecimals(): number {
return this.secondToken?.decimals ?? FPNumber.DEFAULT_PRECISION;
}

get firstTokenPrice(): Nullable<CodecString> {
if (!this.firstToken) return null;

return this.getAssetFiatPrice(this.firstToken);
}

get secondTokenPrice(): Nullable<CodecString> {
if (!this.secondToken) return null;

return this.getAssetFiatPrice(this.secondToken);
}

handleMaxValue(token: Nullable<AccountAsset>, setValue: (v: string) => Promise<void>): void {
if (!token) return;
setValue(getMaxValue(token, this.networkFee));
Expand All @@ -156,10 +121,6 @@ const TokenPairMixinInstance = (namespace: TokenPairNamespace) => {
return getAssetBalance(token);
}

getFormattedTokenBalance(token: any): string {
return formatAssetBalance(token);
}

openSelectSecondTokenDialog(): void {
this.showSelectSecondTokenDialog = true;
}
Expand Down
3 changes: 3 additions & 0 deletions src/components/mixins/TranslationMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component, Mixins } from 'vue-property-decorator';
import { mixins } from '@soramitsu/soraneo-wallet-web';

import { state } from '@/store/decorators';
import { TranslationConsts } from '@/consts';

const OrdinalRules = {
en: (v) => {
Expand All @@ -21,6 +22,8 @@ const OrdinalRules = {

@Component
export default class TranslationMixin extends Mixins(mixins.TranslationMixin) {
readonly TranslationConsts = TranslationConsts;

@state.settings.language language!: string;

tOrdinal(n) {
Expand Down
7 changes: 7 additions & 0 deletions src/consts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export enum Components {
ReferralsConfirmBonding = 'Referrals/ConfirmBonding',
ReferralsConfirmInviteUser = 'Referrals/ConfirmInviteUser',
TokenSelectButton = 'Input/TokenSelectButton',
TokenInput = 'Input/TokenInput',
SelectLanguageDialog = 'SelectLanguageDialog',
SelectAssetList = 'SelectAsset/List',
SelectToken = 'SelectAsset/SelectToken',
Expand Down Expand Up @@ -375,3 +376,9 @@ export const EthereumGasLimits = [

export const MaxUint256 = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff';
export const EthAddress = '0x0000000000000000000000000000000000000000';

// TODO: merge with TranslationConsts from wallet
export enum TranslationConsts {
APR = 'APR', // Annual percentage rate
ROI = 'ROI', // Return of investment
}
5 changes: 4 additions & 1 deletion src/lang/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,10 @@
},
"amountAdd": "Částka pro stake",
"amountRemove": "Částka k odebrání",
"poweredBy": "Běží na Demeter Farming"
"poweredBy": "Běží na Demeter Farming",
"calculator": "Kalkulačka",
"results": "Výsledek",
"rewards": "{symbol} odměny"
},
"staking": {
"title": "Stakování"
Expand Down
19 changes: 11 additions & 8 deletions src/lang/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@
"polkadotjs": {
"noExtensions": "Es wurde keine Polkadot.js-Erweiterung gefunden. Bitte, installiere sie und lade diese Seite erneut\nhttps:\/\/polkadot.js.org\/extension\/",
"noAccounts": "Es scheint keine Konten in deiner Polkadot.js-Erweiterung zu geben. Bitte, füge ein Konto hinzu und versuche es erneut.",
"noAccount": "Polkadot.js Kontofehler. Bitte, überprüfe dein Konto in der Polkadot.js-Erweiterung",
"noExtension": "Es wurde keine {extension} gefunden. Bitte installieren Sie es und laden Sie diese Seite neu",
"noSigner": "Zugriff abgelehnt. Gehen Sie zu den Erweiterungseinstellungen von {extension} und öffnen Sie \"Website-Zugriff verwalten\", um dies zuzulassen."
"noAccount": "{extension} Kontofehler. Bitte überprüfe dein Konto in der {extension} Erweiterung",
"noExtension": "Es wurde keine {extension} gefunden. Bitte installiere es und lade diese Seite neu",
"noSigner": "Zugriff abgelehnt. Gehe zu den Erweiterungseinstellungen von {extension} und öffne \"Website-Zugriff verwalten\", um dies zuzulassen."
},
"connection": {
"title": "SORA-Netzwerk-Konto",
Expand All @@ -100,7 +100,7 @@
"connect": "Konto verbinden",
"refresh": "Aktualisieren"
},
"selectWallet": "Wählen Sie eine Brieftasche aus, mit der Sie arbeiten möchten",
"selectWallet": "Wähle eine Wallet zum Arbeiten aus",
"wallet": {
"install": "Installieren"
}
Expand Down Expand Up @@ -968,9 +968,9 @@
"download": "QR-Code herunterladen",
"upload": "QR scannen",
"invalid": "Ungültiger QR-Code",
"import": "Importieren Sie ein Bild",
"scan": "Scannen Sie mit der Kamera",
"allowanceError": "Überprüfen Sie die Verfügbarkeit Ihrer Kamera und die Browserberechtigungen, um sie zu verwenden",
"import": "Bild importieren",
"scan": "Mit der Kamera scannen",
"allowanceError": "Überprüfe die Verfügbarkeit deiner Kamera und die Browserberechtigungen, um sie zu verwenden",
"receive": "Erhalten"
},
"bridgeTransferNotification": {
Expand Down Expand Up @@ -1015,7 +1015,10 @@
},
"amountAdd": "Zu stakender Betrag",
"amountRemove": "Zu entfernender Betrag",
"poweredBy": "Powered by Demeter Farming"
"poweredBy": "Powered by Demeter Farming",
"calculator": "Taschenrechner",
"results": "Ergebnisse",
"rewards": "{symbol} Belohnungen"
},
"staking": {
"title": "Staken"
Expand Down
5 changes: 4 additions & 1 deletion src/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,10 @@
},
"amountAdd": "Amount to stake",
"amountRemove": "Amount to remove",
"poweredBy": "Powered by Demeter Farming"
"poweredBy": "Powered by Demeter Farming",
"calculator": "Calculator",
"results": "Results",
"rewards": "{symbol} rewards"
},
"staking": {
"title": "Staking"
Expand Down
Loading

0 comments on commit 7f02bad

Please sign in to comment.