vega-frontend-monorepo/apps/trading/components/market-banner/market-update-state-banner.tsx
m.ray 4f8d6bd876
fix(trading): banner for resume trading (#5849)
Co-authored-by: Art <artur@vegaprotocol.io>
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
2024-02-26 16:17:08 +00:00

184 lines
5.2 KiB
TypeScript

import { type ReactNode } from 'react';
import sortBy from 'lodash/sortBy';
import { format, formatDuration, intervalToDuration } from 'date-fns';
import { type ProposalFragment } from '@vegaprotocol/proposals';
import { MarketUpdateType, ProposalState } from '@vegaprotocol/types';
import {
DApp,
TOKEN_PROPOSAL,
TOKEN_PROPOSALS,
useLinks,
} from '@vegaprotocol/environment';
import { getQuoteName, type Market } from '@vegaprotocol/markets';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import { useT } from '../../lib/use-t';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
export const MarketUpdateStateBanner = ({
market,
proposals,
}: {
market: Market;
proposals: ProposalFragment[];
}) => {
const t = useT();
const governanceLink = useLinks(DApp.Governance);
const openTradingProposals = sortBy(
proposals.filter(
(p) =>
p.terms &&
p.terms.change.__typename === 'UpdateMarketState' &&
p.terms.change.updateType ===
MarketUpdateType.MARKET_STATE_UPDATE_TYPE_RESUME
),
(p) => p.terms?.enactmentDatetime
);
const openProposals = sortBy(
proposals.filter((p) => p.state === ProposalState.STATE_OPEN),
(p) => p.terms?.enactmentDatetime
);
const passedProposals = sortBy(
proposals.filter((p) => p.state === ProposalState.STATE_PASSED),
(p) => p.terms?.enactmentDatetime
);
if (!passedProposals.length && !openProposals.length) {
return null;
}
const name = market.tradableInstrument.instrument.code;
const assetSymbol = getQuoteName(market);
const proposalLink =
!passedProposals.length && openProposals[0]?.id
? governanceLink(TOKEN_PROPOSAL.replace(':id', openProposals[0]?.id))
: undefined;
const openTradingProposalsLink =
openTradingProposals[0]?.__typename === 'Proposal' &&
openTradingProposals[0]?.id
? governanceLink(
TOKEN_PROPOSAL.replace(':id', openTradingProposals[0].id)
)
: openTradingProposals[0]?.__typename === 'ProposalDetail' &&
openTradingProposals[0]?.batchId
? governanceLink(
TOKEN_PROPOSAL.replace(':id', openTradingProposals[0].batchId)
)
: undefined;
const proposalsLink =
openProposals.length > 1 ? governanceLink(TOKEN_PROPOSALS) : undefined;
let content: ReactNode;
if (openTradingProposals.length >= 1) {
content = (
<>
<p className="mb-1">
{t(
'Trading on market {{name}} was suspended by governance. There are open proposals to resume trading on this market.',
{ name }
)}
</p>
<p>
<ExternalLink href={openTradingProposalsLink}>
{t('View proposals')}
</ExternalLink>
</p>
</>
);
} else if (passedProposals.length) {
const { date, duration, price } = getMessageVariables(passedProposals[0]);
content = (
<>
<p className="uppercase mb-1">
{t('Trading on market {{name}} will stop on {{date}}', {
name,
date,
})}
</p>
<p>
{t(
'You will no longer be able to hold a position on this market when it closes in {{duration}}.',
{ duration }
)}{' '}
{price &&
assetSymbol &&
t('The final price will be {{price}} {{assetSymbol}}.', {
price: addDecimalsFormatNumber(price, market.decimalPlaces),
assetSymbol,
})}
</p>
</>
);
} else if (openProposals.length > 1) {
content = (
<>
<p className="uppercase mb-1">
{t(
'Trading on market {{name}} may stop. There are open proposals to close this market',
{ name }
)}
</p>
<p>
<ExternalLink href={proposalsLink}>
{t('View proposals')}
</ExternalLink>
</p>
</>
);
} else {
const { date, price } = getMessageVariables(openProposals[0]);
content = (
<>
<p className="mb-1">
{t(
'Trading on market {{name}} may stop on {{date}}. There is an open proposal to close this market.',
{ name, date }
)}
</p>
<p>
{price &&
assetSymbol &&
t('Proposed final price is {{price}} {{assetSymbol}}.', {
price: addDecimalsFormatNumber(price, market.decimalPlaces),
assetSymbol,
})}{' '}
<ExternalLink href={proposalLink}>{t('View proposal')}</ExternalLink>
</p>
</>
);
}
return <div data-testid={`update-state-banner-${market.id}`}>{content}</div>;
};
const getMessageVariables = (proposal: ProposalFragment) => {
const enactmentDatetime =
proposal.terms && new Date(proposal.terms.enactmentDatetime);
const date = enactmentDatetime && format(enactmentDatetime, 'dd MMMM');
const duration =
enactmentDatetime &&
formatDuration(
intervalToDuration({
start: new Date(),
end: enactmentDatetime,
}),
{
format: ['days', 'hours'],
}
);
const price =
proposal.terms?.change.__typename === 'UpdateMarketState'
? proposal.terms.change.price
: '';
return {
date,
duration,
price,
};
};