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 = ( <>

{t( 'Trading on market {{name}} was suspended by governance. There are open proposals to resume trading on this market.', { name } )}

{t('View proposals')}

); } else if (passedProposals.length) { const { date, duration, price } = getMessageVariables(passedProposals[0]); content = ( <>

{t('Trading on market {{name}} will stop on {{date}}', { name, date, })}

{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, })}

); } else if (openProposals.length > 1) { content = ( <>

{t( 'Trading on market {{name}} may stop. There are open proposals to close this market', { name } )}

{t('View proposals')}

); } else { const { date, price } = getMessageVariables(openProposals[0]); content = ( <>

{t( 'Trading on market {{name}} may stop on {{date}}. There is an open proposal to close this market.', { name, date } )}

{price && assetSymbol && t('Proposed final price is {{price}} {{assetSymbol}}.', { price: addDecimalsFormatNumber(price, market.decimalPlaces), assetSymbol, })}{' '} {t('View proposal')}

); } return
{content}
; }; 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, }; };