vega-frontend-monorepo/libs/wallet/src/vega-transaction-dialog/vega-transaction-dialog.tsx
m.ray 8ce51dddbc
Feat/625 market info more details - open interest, liquidity info, market and instrument ids, price and settlement asset in the header - Part 1 (#823)
* fix: #625 update the info market query with new fields

* fix: #625 generate code for info market query and fix pagination being removed from globalTypes

* fix:  add id and filter no trading auctions

* fix: add id and format labels

* fix: add name and code to instrument

* fix: add name and code to instrument

* fix: format check

* feat: add settlement asset and mark price

* feat: add liquidity parameters

* fix: remove settings.json

* fix: price instead of mark price label

* fix: add instrument metadata

* fix: remove unused set lodash

* fix: move Liquidity monitoring parameters after price monitoring

* fix: rename instrument metadata to metadata

* fix: settlement asset could be undefined

* Merge branch 'master' of github.com:vegaprotocol/frontend-monorepo into feat/625-market-info-more-details-open-interest-liquidity-ids-risk

* fix: format market id and trading mode label in key details

* fix: display settlement asset if defined

* fix: format trade-grid.tsx
2022-07-21 10:57:30 +01:00

267 lines
7.0 KiB
TypeScript

import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
import { useEffect } from 'react';
import type { VegaTxState } from '../use-vega-transaction';
import { VegaTxStatus } from '../use-vega-transaction';
import { Icon, Loader } from '@vegaprotocol/ui-toolkit';
import type { ReactNode } from 'react';
import {
addDecimalsFormatNumber,
formatLabel,
t,
} from '@vegaprotocol/react-helpers';
import { useEnvironment } from '@vegaprotocol/environment';
import { OrderType } from '@vegaprotocol/types';
import type { Order } from '../wallet-types';
import get from 'lodash/get';
export interface VegaTransactionDialogProps {
orderDialogOpen: boolean;
setOrderDialogOpen: (isOpen: boolean) => void;
finalizedOrder: Order | null;
transaction: VegaTxState;
reset: () => void;
title?: string;
children?: ReactNode;
}
const getDialogIntent = (
finalizedOrder: Order | null,
transaction: VegaTxState
) => {
if (finalizedOrder) {
return !finalizedOrder.rejectionReason ? Intent.Success : Intent.Danger;
}
switch (transaction.status) {
case VegaTxStatus.Requested:
return Intent.Warning;
case VegaTxStatus.Pending:
return Intent.Warning;
case VegaTxStatus.Error:
return Intent.Danger;
default:
return Intent.None;
}
};
export const VegaTransactionDialog = ({
orderDialogOpen,
setOrderDialogOpen,
finalizedOrder,
transaction,
reset,
title = '',
children,
}: VegaTransactionDialogProps) => {
// open / close dialog
useEffect(() => {
if (transaction.status !== VegaTxStatus.Default || finalizedOrder) {
setOrderDialogOpen(true);
} else {
setOrderDialogOpen(false);
}
}, [finalizedOrder, setOrderDialogOpen, transaction.status]);
return (
<Dialog
open={orderDialogOpen}
onChange={(isOpen) => {
setOrderDialogOpen(isOpen);
// If closing reset
if (!isOpen) {
reset();
}
}}
intent={getDialogIntent(finalizedOrder, transaction)}
>
<VegaDialog
key={`${title.toLowerCase().split(' ').join('-')}-tx-${
transaction.txHash
}`}
transaction={transaction}
finalizedOrder={finalizedOrder}
title={title}
children={children}
/>
</Dialog>
);
};
interface VegaDialogProps {
transaction: VegaTxState;
finalizedOrder: Order | null;
title: string;
children?: ReactNode;
}
export const VegaDialog = ({
transaction,
finalizedOrder,
title,
children,
}: VegaDialogProps) => {
const { VEGA_EXPLORER_URL } = useEnvironment();
const headerClassName = 'text-h5 font-bold text-black dark:text-white';
if (children && transaction.status === VegaTxStatus.Default) {
return <div>{children}</div>;
}
// Rejected by wallet
if (transaction.status === VegaTxStatus.Requested) {
return (
<OrderDialogWrapper
title="Confirm transaction in wallet"
icon={<Icon name="hand-up" size={20} />}
>
<p>
{t(
'Please open your wallet application and confirm or reject the transaction'
)}
</p>
</OrderDialogWrapper>
);
}
// Transaction error
if (transaction.status === VegaTxStatus.Error) {
return (
<OrderDialogWrapper
title="Order rejected by wallet"
icon={<Icon name="warning-sign" size={20} />}
>
{transaction.error && (
<pre className="text-ui break-all whitespace-pre-wrap">
{get(transaction.error, 'error') ??
JSON.stringify(transaction.error, null, 2)}
</pre>
)}
</OrderDialogWrapper>
);
}
// Pending consensus
if (!finalizedOrder) {
return (
<OrderDialogWrapper
title="Awaiting network confirmation"
icon={<Loader size="small" />}
>
{transaction.txHash && (
<p className="break-all">
{t('Waiting for few more blocks')} - &nbsp;
<a
className="underline"
data-testid="tx-block-explorer"
href={`${VEGA_EXPLORER_URL}/txs/0x${transaction.txHash}`}
target="_blank"
rel="noreferrer"
>
{t('View in block explorer')}
</a>
</p>
)}
</OrderDialogWrapper>
);
}
// Order on network but was rejected
if (finalizedOrder.status === 'Rejected') {
return (
<OrderDialogWrapper
title="Order failed"
icon={<Icon name="warning-sign" size={20} />}
>
<p data-testid="error-reason">
{finalizedOrder.rejectionReason &&
t(`Reason: ${formatLabel(finalizedOrder.rejectionReason)}`)}
</p>
</OrderDialogWrapper>
);
}
return (
<OrderDialogWrapper title={title} icon={<Icon name="tick" size={20} />}>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
{finalizedOrder.market && (
<div>
<p className={headerClassName}>{t(`Market`)}</p>
<p>{t(`${finalizedOrder.market.name}`)}</p>
</div>
)}
<div>
<p className={headerClassName}>{t(`Status`)}</p>
<p>{t(`${finalizedOrder.status}`)}</p>
</div>
{finalizedOrder.type === OrderType.Limit && finalizedOrder.market && (
<div>
<p className={headerClassName}>{t(`Price`)}</p>
<p>
{addDecimalsFormatNumber(
finalizedOrder.price,
finalizedOrder.market.decimalPlaces
)}
</p>
</div>
)}
<div>
<p className={headerClassName}>{t(`Amount`)}</p>
<p
className={
finalizedOrder.side === 'Buy'
? 'text-vega-green'
: 'text-vega-red'
}
>
{`${finalizedOrder.side === 'Buy' ? '+' : '-'} ${
finalizedOrder.size
}
`}
</p>
</div>
</div>
<div className="grid grid-cols-1 gap-8">
{transaction.txHash && (
<div>
<p className={headerClassName}>{t(`Transaction`)}</p>
<a
className="underline break-words"
data-testid="tx-block-explorer"
href={`${VEGA_EXPLORER_URL}/txs/0x${transaction.txHash}`}
target="_blank"
rel="noreferrer"
>
{transaction.txHash}
</a>
</div>
)}
</div>
</OrderDialogWrapper>
);
};
interface OrderDialogWrapperProps {
children: ReactNode;
icon: ReactNode;
title: string;
}
export const OrderDialogWrapper = ({
children,
icon,
title,
}: OrderDialogWrapperProps) => {
const headerClassName = 'text-h4 font-bold text-black dark:text-white';
return (
<div className="flex gap-12 max-w-full">
<div className="pt-8 fill-current">{icon}</div>
<div data-testid="order-wrapper" className="flex-1">
<h1 data-testid="order-status-header" className={headerClassName}>
{title}
</h1>
{children}
</div>
</div>
);
};