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

APR Calculator #754

Merged
merged 16 commits into from
Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
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