Skip to content

Commit

Permalink
Feat: Operations parameters fiat amount (#1098)
Browse files Browse the repository at this point in the history
* Feat: Price provider model (#1084)

* Feat: Currency settings (#1076)

* Feat: fiat balance assets and staking (#1087)

* Feat: amount input currency (#1083)

* feat: currency select modal

* chore: added icon for currency

* feat: added currency mode to amount input

* feat: price provider model

* feat: load assets prices

* chore: code style, export events

* feat: integrated currency modal to currenc settings

* chore: updated crouped select semantics

* chore: fixed General Action test

* chore: fixed grouped select active state

* feat: tests for models, review fixes

* chore: fixed pr comments

* chore: added currency form model

* fix: fixed modal reload after submit

* feat: [wip] amount input currency integration

* chore: removed button disabled condition

* feat: amount input with currency integration

* fix: tests

* feat: form model, test

* chore: removed GroupedSelect

* fix: ui
fix: correct input for priceless asset

* fix: revert commented code

---------

Co-authored-by: Egor B <[email protected]>
Co-authored-by: Yaroslav Grachev <[email protected]>
Co-authored-by: asmadek <[email protected]>

* feat: added fiat amount for transfer and multisig operations

* feat: added fiat values to staking operations

---------

Co-authored-by: Yaroslav Grachev <[email protected]>
Co-authored-by: Aleksandr Makhnev <[email protected]>
Co-authored-by: Egor B <[email protected]>
  • Loading branch information
4 people authored Sep 29, 2023
1 parent 074a53b commit 9d88856
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 47 deletions.
9 changes: 7 additions & 2 deletions src/renderer/entities/transaction/ui/Deposit/Deposit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useEffect, useState, memo } from 'react';
import { Asset, AssetBalance } from '@renderer/entities/asset';
import { Threshold } from '@renderer/domain/shared-kernel';
import { useTransaction } from '@renderer/entities/transaction';
import { AssetFiatBalance } from '@renderer/entities/price/ui/AssetFiatBalance';

type Props = {
api: ApiPromise;
Expand All @@ -15,7 +16,6 @@ type Props = {

export const Deposit = memo(({ api, asset, threshold, className, onDepositChange }: Props) => {
const { getTransactionDeposit } = useTransaction();

const [deposit, setDeposit] = useState('');

useEffect(() => {
Expand All @@ -25,5 +25,10 @@ export const Deposit = memo(({ api, asset, threshold, className, onDepositChange
onDepositChange?.(txDeposit);
}, [threshold, api]);

return <AssetBalance className={className} value={deposit} asset={asset} />;
return (
<div className="flex flex-col gap-y-0.5 items-end">
<AssetBalance value={deposit} asset={asset} className={className} />
<AssetFiatBalance asset={asset} amount={deposit} />
</div>
);
});
18 changes: 16 additions & 2 deletions src/renderer/entities/transaction/ui/Fee/Fee.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { ApiPromise } from '@polkadot/api';
import { BN } from '@polkadot/util';
import { useEffect, useState, memo } from 'react';
import { useUnit } from 'effector-react';

import { Asset, AssetBalance } from '@renderer/entities/asset';
import { Transaction, useTransaction } from '@renderer/entities/transaction';
import { Shimmering } from '@renderer/shared/ui';
import { priceProviderModel } from '@renderer/entities/price';
import { AssetFiatBalance } from '@renderer/entities/price/ui/AssetFiatBalance';

type Props = {
api: ApiPromise;
Expand All @@ -18,6 +21,7 @@ type Props = {

export const Fee = memo(({ api, multiply = 1, asset, transaction, className, onFeeChange, onFeeLoading }: Props) => {
const { getTransactionFee } = useTransaction();
const fiatFlag = useUnit(priceProviderModel.$fiatFlag);

const [fee, setFee] = useState('');
const [isLoading, setIsLoading] = useState(false);
Expand Down Expand Up @@ -49,10 +53,20 @@ export const Fee = memo(({ api, multiply = 1, asset, transaction, className, onF
}, [transaction, api]);

if (isLoading) {
return <Shimmering width={90} height={20} data-testid="fee-loader" />;
return (
<div className="flex flex-col gap-y-0.5 items-end">
<Shimmering width={90} height={20} data-testid="fee-loader" />
{fiatFlag && <Shimmering width={70} height={18} data-testid="fee-loader" />}
</div>
);
}

const totalFee = new BN(fee).muln(multiply).toString();

return <AssetBalance value={totalFee} asset={asset} className={className} />;
return (
<div className="flex flex-col gap-y-0.5 items-end">
<AssetBalance value={totalFee} asset={asset} className={className} />
<AssetFiatBalance asset={asset} amount={totalFee} />
</div>
);
});
18 changes: 16 additions & 2 deletions src/renderer/entities/transaction/ui/XcmFee/XcmFee.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { BN } from '@polkadot/util';
import { useEffect, useState, memo } from 'react';
import { ApiPromise } from '@polkadot/api';
import { useUnit } from 'effector-react';

import { Asset, AssetBalance } from '@renderer/entities/asset';
import { Transaction } from '@renderer/entities/transaction';
import { Shimmering } from '@renderer/shared/ui';
import { estimateFee, XcmConfig } from '@renderer/shared/api/xcm';
import { toLocalChainId } from '@renderer/shared/lib/utils';
import { priceProviderModel } from '@renderer/entities/price';
import { AssetFiatBalance } from '@renderer/entities/price/ui/AssetFiatBalance';

type Props = {
api?: ApiPromise;
Expand All @@ -23,6 +26,7 @@ export const XcmFee = memo(
({ multiply = 1, config, asset, transaction, className, onFeeChange, onFeeLoading, api }: Props) => {
const [fee, setFee] = useState('0');
const [isLoading, setIsLoading] = useState(false);
const fiatFlag = useUnit(priceProviderModel.$fiatFlag);

const updateFee = (fee: string) => {
setFee(fee);
Expand Down Expand Up @@ -68,11 +72,21 @@ export const XcmFee = memo(
}, [transaction]);

if (isLoading) {
return <Shimmering width={90} height={20} data-testid="fee-loader" />;
return (
<div className="flex flex-col gap-y-0.5 items-end">
<Shimmering width={90} height={20} data-testid="fee-loader" />
{fiatFlag && <Shimmering width={70} height={18} data-testid="fee-loader" />}
</div>
);
}

const totalFee = new BN(fee).muln(multiply).toString();

return <AssetBalance value={totalFee} asset={asset} className={className} />;
return (
<div className="flex flex-col gap-y-0.5 items-end">
<AssetBalance value={totalFee} asset={asset} className={className} />
<AssetFiatBalance asset={asset} amount={totalFee} />
</div>
);
},
);
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import { useI18n } from '@renderer/app/providers';
import { getIconName } from '../../common/utils';
import Details from '../Details';

const AmountFontStyle = 'font-manrope text-text-primary text-[32px] leading-[36px] font-bold';

type Props = {
tx: MultisigTransaction;
account: MultisigAccount;
Expand All @@ -27,7 +25,7 @@ export const Confirmation = ({ tx, account, connection, feeTx }: Props) => {
<Icon className="text-icon-default" name={iconName} size={42} />
</div>

{tx.transaction && <TransactionAmount tx={tx.transaction} showIcon={false} className={AmountFontStyle} />}
{tx.transaction && <TransactionAmount tx={tx.transaction} />}

{tx.description && (
<FootnoteText className="py-2 px-3 rounded bg-block-background ml-3 text-text-secondary">
Expand Down
23 changes: 9 additions & 14 deletions src/renderer/pages/Operations/components/Log.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@ import { format } from 'date-fns';

import { useI18n } from '@renderer/app/providers';
import { Account, MultisigAccount } from '@renderer/entities/account';
import { ExtendedChain } from '@renderer/entities/network';
import { chainsService, ExtendedChain } from '@renderer/entities/network';
import { MultisigEvent, SigningStatus } from '@renderer/entities/transaction/model/transaction';
import { TransferTypes, XcmTypes } from '@renderer/entities/transaction/lib/common/constants';
import { TransactionTitle } from './TransactionTitle/TransactionTitle';
import OperationStatus from './OperationStatus';
import { getSignatoryName, sortByDateAsc } from '../common/utils';
import { getSignatoryName, getTransactionAmount, sortByDateAsc } from '../common/utils';
import { BaseModal, BodyText, FootnoteText, Identicon } from '@renderer/shared/ui';
import { toAddress, SS58_DEFAULT_PREFIX } from '@renderer/shared/lib/utils';
import { toAddress, SS58_DEFAULT_PREFIX, getAssetById } from '@renderer/shared/lib/utils';
import { ExtrinsicExplorers } from '@renderer/components/common';
import { Contact } from '@renderer/entities/contact';
import { useMultisigEvent } from '@renderer/entities/multisig';
import { MultisigTransactionDS } from '@renderer/shared/api/storage';
import { TransactionAmount } from '../components/TransactionAmount';
import { AssetBalance } from '@renderer/entities/asset';

type Props = {
tx: MultisigTransactionDS;
Expand Down Expand Up @@ -43,6 +42,10 @@ const LogModal = ({ isOpen, onClose, tx, account, connection, contacts, accounts
const { transaction, description, status } = tx;
const approvals = events.filter((e) => e.status === 'SIGNED');

const asset =
tx.transaction && getAssetById(tx.transaction.args.asset, chainsService.getChainById(tx.chainId)?.assets);
const amount = tx.transaction && getTransactionAmount(tx.transaction);

const addressPrefix = connection?.addressPrefix || SS58_DEFAULT_PREFIX;

const groupedEvents = groupBy(events, ({ dateCreated }) =>
Expand All @@ -66,12 +69,6 @@ const LogModal = ({ isOpen, onClose, tx, account, connection, contacts, accounts
return `${signatoryName} ${t(eventMessage)}`;
};

const showTxAmount = (): boolean => {
if (!transaction?.type) return false;

return [...TransferTypes, ...XcmTypes].includes(transaction.type);
};

return (
<BaseModal
title={t('log.title')}
Expand All @@ -84,9 +81,7 @@ const LogModal = ({ isOpen, onClose, tx, account, connection, contacts, accounts
>
<div className="flex gap-2 items-center justify-between px-4 py-3">
<TransactionTitle className="overflow-hidden" tx={transaction} description={description}>
{transaction && showTxAmount() && (
<TransactionAmount className="truncate" tx={transaction} showIcon={false} />
)}
{asset && amount && <AssetBalance value={amount} asset={asset} className="truncate" />}
</TransactionTitle>

<OperationStatus
Expand Down
15 changes: 12 additions & 3 deletions src/renderer/pages/Operations/components/Operation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import { useI18n } from '@renderer/app/providers';
import { TransactionTitle } from './TransactionTitle/TransactionTitle';
import { MultisigAccount } from '@renderer/entities/account';
import { FootnoteText, Accordion } from '@renderer/shared/ui';
import { TransactionAmount } from './TransactionAmount';
import OperationStatus from './OperationStatus';
import OperationFullInfo from './OperationFullInfo';
import { MultisigTransactionDS } from '@renderer/shared/api/storage';
import { useMultisigEvent } from '@renderer/entities/multisig';
import { ChainTitle, XcmChains } from '@renderer/entities/chain';
import { getTransactionAmount } from '../common/utils';
import { isXcmTransaction } from '@renderer/entities/transaction';
import { chainsService } from '@renderer/entities/network';
import { getAssetById } from '@renderer/shared/lib/utils';
import { AssetBalance } from '@renderer/entities/asset';

type Props = {
tx: MultisigTransactionDS;
Expand All @@ -26,6 +28,9 @@ const Operation = ({ tx, account }: Props) => {
const approvals = events?.filter((e) => e.status === 'SIGNED') || [];
const initEvent = approvals.find((e) => e.accountId === tx.depositor);
const date = new Date(tx.dateCreated || initEvent?.dateCreated || Date.now());
const asset =
tx.transaction && getAssetById(tx.transaction.args.asset, chainsService.getChainById(tx.chainId)?.assets);
const amount = tx.transaction && getTransactionAmount(tx.transaction);

return (
<Accordion className="bg-block-background-default transition-shadow rounded hover:shadow-card-shadow focus-visible:shadow-card-shadow">
Expand All @@ -39,8 +44,12 @@ const Operation = ({ tx, account }: Props) => {

<TransactionTitle className="flex-1 overflow-hidden" tx={tx.transaction} description={tx.description} />

{tx.transaction && getTransactionAmount(tx.transaction) && (
<TransactionAmount wrapperClassName="w-[160px]" tx={tx.transaction} />
{asset && amount ? (
<div className="w-[160px]">
<AssetBalance value={amount} asset={asset} showIcon />
</div>
) : (
<span className="w-[160px]" />
)}

{isXcmTransaction(tx.transaction) ? (
Expand Down
33 changes: 16 additions & 17 deletions src/renderer/pages/Operations/components/TransactionAmount.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
import { useEffect, useState, ComponentProps } from 'react';

import { DecodedTransaction, Transaction } from '@renderer/entities/transaction';
import { chainsService } from '@renderer/entities/network';
import { Asset, AssetBalance } from '@renderer/entities/asset';
import { getAssetById } from '@renderer/shared/lib/utils';
import { AssetBalance } from '@renderer/entities/asset';
import { cnTw, getAssetById } from '@renderer/shared/lib/utils';
import { getTransactionAmount } from '../common/utils';
import { AssetFiatBalance } from '@renderer/entities/price/ui/AssetFiatBalance';

type Props = {
tx: Transaction | DecodedTransaction;
className?: string;
};

type BalanceProps = Pick<ComponentProps<typeof AssetBalance>, 'className' | 'showIcon' | 'wrapperClassName'>;

export const TransactionAmount = ({ tx, ...balanceProps }: Props & BalanceProps) => {
const [assets, setAssets] = useState<Asset[]>([]);

useEffect(() => {
const chain = chainsService.getChainById(tx.chainId);

setAssets(chain?.assets || []);
}, []);

const asset = getAssetById(tx.args.asset, assets);
export const TransactionAmount = ({ tx, className }: Props) => {
const asset = tx && getAssetById(tx.args.asset, chainsService.getChainById(tx.chainId)?.assets);
const value = getTransactionAmount(tx);

if (!asset || !value) return null;

return <AssetBalance value={value} asset={asset} showIcon {...balanceProps} />;
return (
<div className={cnTw('flex flex-col gap-y-1 items-center')}>
<AssetBalance
value={value}
asset={asset}
className={cnTw('font-manrope text-text-primary text-[32px] leading-[36px] font-bold', className)}
/>
<AssetFiatBalance asset={asset} amount={value} className="text-headline" />
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import ValidatorsModal from '../Modals/ValidatorsModal/ValidatorsModal';
import { DestinationType } from '../../common/types';
import { cnTw } from '@renderer/shared/lib/utils';
import { useMultisigTx } from '@renderer/entities/multisig';
import { AssetFiatBalance } from '@renderer/entities/price/ui/AssetFiatBalance';

const ActionStyle = 'group hover:bg-action-background-hover px-2 py-1 rounded';

Expand Down Expand Up @@ -88,7 +89,14 @@ export const Confirmation = ({
<div className="w-[440px] px-5 py-4">
<div className="flex flex-col items-center gap-y-3 mb-6">
{amounts.length > 0 && (
<AssetBalance className="block mx-auto text-center text-4xl font-bold" value={totalAmount} asset={asset} />
<div className="flex flex-col gap-y-1 items-center mx-auto">
<AssetBalance
value={totalAmount}
asset={asset}
className="font-manrope text-text-primary text-[32px] leading-[36px] font-bold"
/>
<AssetFiatBalance asset={asset} amount={totalAmount} className="text-headline" />
</div>
)}

{description && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import { Wallet, useWallet } from '@renderer/entities/wallet';
import { XcmFee } from '@renderer/entities/transaction/ui/XcmFee/XcmFee';
import { AssetXCM, XcmConfig } from '@renderer/shared/api/xcm';

const AmountFontStyle = 'font-manrope text-text-primary text-[32px] leading-[36px] font-bold';

type Props = {
transaction: Transaction;
account: Account | MultisigAccount;
Expand Down Expand Up @@ -60,7 +58,7 @@ export const Confirmation = ({
</div>
)}

{transaction && <TransactionAmount tx={transaction} showIcon={false} className={AmountFontStyle} />}
{transaction && <TransactionAmount tx={transaction} />}

{description && (
<FootnoteText className="py-2 px-3 rounded bg-block-background ml-3 text-text-secondary">
Expand Down

0 comments on commit 9d88856

Please sign in to comment.