feat(governance,markets,ui-toolkit): highlight successor market changes (#4449)
Co-authored-by: Joe <joe@vega.xyz>
This commit is contained in:
parent
26d5a67604
commit
8d31510d5e
@ -730,6 +730,7 @@ context(
|
||||
.getByTestId('key-value-table-row')
|
||||
.contains(heading)
|
||||
.parent()
|
||||
.parent()
|
||||
.siblings();
|
||||
}
|
||||
}
|
||||
|
@ -45,8 +45,10 @@ export const useMarketDataDialogStore = create<MarketDataDialogState>(
|
||||
|
||||
export const ProposalMarketData = ({
|
||||
marketData,
|
||||
parentMarketData,
|
||||
}: {
|
||||
marketData: MarketInfoWithData;
|
||||
parentMarketData?: MarketInfoWithData;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { isOpen, open, close } = useMarketDataDialogStore();
|
||||
@ -58,8 +60,21 @@ export const ProposalMarketData = ({
|
||||
|
||||
const settlementData = marketData.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForSettlementData.data as DataSourceDefinition;
|
||||
const parentSettlementData =
|
||||
parentMarketData?.tradableInstrument.instrument?.product
|
||||
?.dataSourceSpecForSettlementData?.data;
|
||||
const terminationData = marketData.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForTradingTermination.data as DataSourceDefinition;
|
||||
const parentTerminationData =
|
||||
parentMarketData?.tradableInstrument.instrument?.product
|
||||
?.dataSourceSpecForTradingTermination?.data;
|
||||
|
||||
const isParentSettlementDataEqual =
|
||||
parentSettlementData !== undefined &&
|
||||
isEqual(settlementData, parentSettlementData);
|
||||
const isParentTerminationDataEqual =
|
||||
parentTerminationData !== undefined &&
|
||||
isEqual(terminationData, parentTerminationData);
|
||||
|
||||
const getSigners = (data: DataSourceDefinition) => {
|
||||
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
|
||||
@ -97,12 +112,22 @@ export const ProposalMarketData = ({
|
||||
<AccordionItem
|
||||
itemId="key-details"
|
||||
title={t('Key details')}
|
||||
content={<KeyDetailsInfoPanel market={marketData} />}
|
||||
content={
|
||||
<KeyDetailsInfoPanel
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<AccordionItem
|
||||
itemId="instrument"
|
||||
title={t('Instrument')}
|
||||
content={<InstrumentInfoPanel market={marketData} />}
|
||||
content={
|
||||
<InstrumentInfoPanel
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
{isEqual(
|
||||
getSigners(settlementData),
|
||||
@ -115,6 +140,11 @@ export const ProposalMarketData = ({
|
||||
<OracleInfoPanel
|
||||
market={marketData}
|
||||
type="settlementData"
|
||||
parentMarket={
|
||||
isParentSettlementDataEqual
|
||||
? undefined
|
||||
: parentMarketData
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
@ -127,6 +157,11 @@ export const ProposalMarketData = ({
|
||||
<OracleInfoPanel
|
||||
market={marketData}
|
||||
type="settlementData"
|
||||
parentMarket={
|
||||
isParentSettlementDataEqual
|
||||
? undefined
|
||||
: parentMarketData
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
@ -135,11 +170,21 @@ export const ProposalMarketData = ({
|
||||
itemId="termination-oracle"
|
||||
title={t('Termination Oracle')}
|
||||
content={
|
||||
<OracleInfoPanel market={marketData} type="termination" />
|
||||
<OracleInfoPanel
|
||||
market={marketData}
|
||||
type="termination"
|
||||
parentMarket={
|
||||
isParentTerminationDataEqual
|
||||
? undefined
|
||||
: parentMarketData
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{/*Note: successor markets will not differ in their settlement*/}
|
||||
{/*assets, so no need to pass in parent market data for comparison.*/}
|
||||
<AccordionItem
|
||||
itemId="settlement-asset"
|
||||
title={t('Settlement asset')}
|
||||
@ -148,22 +193,42 @@ export const ProposalMarketData = ({
|
||||
<AccordionItem
|
||||
itemId="metadata"
|
||||
title={t('Metadata')}
|
||||
content={<MetadataInfoPanel market={marketData} />}
|
||||
content={
|
||||
<MetadataInfoPanel
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<AccordionItem
|
||||
itemId="risk-model"
|
||||
title={t('Risk model')}
|
||||
content={<RiskModelInfoPanel market={marketData} />}
|
||||
content={
|
||||
<RiskModelInfoPanel
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<AccordionItem
|
||||
itemId="risk-parameters"
|
||||
title={t('Risk parameters')}
|
||||
content={<RiskParametersInfoPanel market={marketData} />}
|
||||
content={
|
||||
<RiskParametersInfoPanel
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<AccordionItem
|
||||
itemId="risk-factors"
|
||||
title={t('Risk factors')}
|
||||
content={<RiskFactorsInfoPanel market={marketData} />}
|
||||
content={
|
||||
<RiskFactorsInfoPanel
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
{(
|
||||
marketData.priceMonitoringSettings?.parameters?.triggers || []
|
||||
@ -174,6 +239,7 @@ export const ProposalMarketData = ({
|
||||
content={
|
||||
<PriceMonitoringBoundsInfoPanel
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
triggerIndex={triggerIndex}
|
||||
/>
|
||||
}
|
||||
@ -183,13 +249,21 @@ export const ProposalMarketData = ({
|
||||
itemId="liqudity-monitoring-parameters"
|
||||
title={t('Liquidity monitoring parameters')}
|
||||
content={
|
||||
<LiquidityMonitoringParametersInfoPanel market={marketData} />
|
||||
<LiquidityMonitoringParametersInfoPanel
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<AccordionItem
|
||||
itemId="liquidity-price-range"
|
||||
title={t('Liquidity price range')}
|
||||
content={<LiquidityPriceRangeInfoPanel market={marketData} />}
|
||||
content={
|
||||
<LiquidityPriceRangeInfoPanel
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Accordion>
|
||||
</div>
|
||||
|
@ -32,6 +32,7 @@ export interface ProposalProps {
|
||||
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||
networkParams: Partial<NetworkParamsResult>;
|
||||
newMarketData?: MarketInfoWithData | null;
|
||||
parentMarketData?: MarketInfoWithData | null;
|
||||
assetData?: AssetQuery | null;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
restData: any;
|
||||
@ -46,6 +47,7 @@ export const Proposal = ({
|
||||
networkParams,
|
||||
restData,
|
||||
newMarketData,
|
||||
parentMarketData,
|
||||
assetData,
|
||||
originalMarketProposalRestData,
|
||||
mostRecentlyEnactedAssociatedMarketProposal,
|
||||
@ -157,7 +159,10 @@ export const Proposal = ({
|
||||
|
||||
{newMarketData && (
|
||||
<div className="mb-4">
|
||||
<ProposalMarketData marketData={newMarketData} />
|
||||
<ProposalMarketData
|
||||
marketData={newMarketData}
|
||||
parentMarketData={parentMarketData ? parentMarketData : undefined}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
@ -14,6 +14,9 @@ import {
|
||||
NetworkParams,
|
||||
useNetworkParams,
|
||||
} from '@vegaprotocol/network-parameters';
|
||||
import { useParentMarketIdQuery } from '@vegaprotocol/markets';
|
||||
import { FLAGS } from '@vegaprotocol/environment';
|
||||
import { useSuccessorMarketProposalDetails } from '@vegaprotocol/proposals';
|
||||
|
||||
export const ProposalContainer = () => {
|
||||
const [
|
||||
@ -54,6 +57,10 @@ export const ProposalContainer = () => {
|
||||
skip: !params.proposalId,
|
||||
});
|
||||
|
||||
const successor = useSuccessorMarketProposalDetails(params.proposalId);
|
||||
|
||||
const isSuccessor = !!successor?.parentMarketId || !!successor.code;
|
||||
|
||||
const {
|
||||
state: {
|
||||
data: originalMarketProposalRestData,
|
||||
@ -96,6 +103,36 @@ export const ProposalContainer = () => {
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
data: parentMarketId,
|
||||
loading: parentMarketIdLoading,
|
||||
error: parentMarketIdError,
|
||||
} = useParentMarketIdQuery({
|
||||
variables: {
|
||||
marketId: newMarketData?.data?.market?.id || '',
|
||||
},
|
||||
skip:
|
||||
!FLAGS.SUCCESSOR_MARKETS ||
|
||||
!isSuccessor ||
|
||||
!newMarketData?.data?.market?.id,
|
||||
});
|
||||
|
||||
const {
|
||||
data: parentMarketData,
|
||||
loading: parentMarketLoading,
|
||||
error: parentMarketError,
|
||||
} = useDataProvider({
|
||||
dataProvider: marketInfoWithDataProvider,
|
||||
skipUpdates: true,
|
||||
variables: {
|
||||
marketId: parentMarketId?.market?.parentMarketID || '',
|
||||
skip:
|
||||
!FLAGS.SUCCESSOR_MARKETS ||
|
||||
!isSuccessor ||
|
||||
!parentMarketId?.market?.parentMarketID,
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
data: assetData,
|
||||
loading: assetLoading,
|
||||
@ -160,6 +197,8 @@ export const ProposalContainer = () => {
|
||||
newMarketLoading ||
|
||||
assetLoading ||
|
||||
networkParamsLoading ||
|
||||
parentMarketIdLoading ||
|
||||
parentMarketLoading ||
|
||||
(restLoading ? (restLoading as boolean) : false) ||
|
||||
(originalMarketProposalRestLoading
|
||||
? (originalMarketProposalRestLoading as boolean)
|
||||
@ -172,15 +211,18 @@ export const ProposalContainer = () => {
|
||||
error ||
|
||||
newMarketError ||
|
||||
assetError ||
|
||||
networkParamsError ||
|
||||
parentMarketIdError ||
|
||||
parentMarketError ||
|
||||
restError ||
|
||||
originalMarketProposalRestError ||
|
||||
previouslyEnactedMarketProposalsRestError ||
|
||||
networkParamsError
|
||||
previouslyEnactedMarketProposalsRestError
|
||||
}
|
||||
data={{
|
||||
...data,
|
||||
...networkParams,
|
||||
...(newMarketData ? { newMarketData } : {}),
|
||||
...(parentMarketData ? { parentMarketData } : {}),
|
||||
...(assetData ? { assetData } : {}),
|
||||
...(restData ? { restData } : {}),
|
||||
...(originalMarketProposalRestData
|
||||
@ -197,6 +239,7 @@ export const ProposalContainer = () => {
|
||||
networkParams={networkParams}
|
||||
restData={restData}
|
||||
newMarketData={newMarketData}
|
||||
parentMarketData={parentMarketData}
|
||||
assetData={assetData}
|
||||
originalMarketProposalRestData={originalMarketProposalRestData}
|
||||
mostRecentlyEnactedAssociatedMarketProposal={
|
||||
|
@ -28,10 +28,10 @@ export const assetProvider = makeDataProvider<
|
||||
getData,
|
||||
});
|
||||
|
||||
export const useAssetDataProvider = (assetId: string) => {
|
||||
export const useAssetDataProvider = (assetId: string, skip?: boolean) => {
|
||||
return useDataProvider({
|
||||
dataProvider: assetProvider,
|
||||
variables: { assetId: assetId || '' },
|
||||
skip: !assetId,
|
||||
skip: !assetId || skip,
|
||||
});
|
||||
};
|
||||
|
@ -4,8 +4,10 @@ import {
|
||||
} from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
Intent,
|
||||
KeyValueTable,
|
||||
KeyValueTableRow,
|
||||
Lozenge,
|
||||
Tooltip,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import BigNumber from 'bignumber.js';
|
||||
@ -22,9 +24,11 @@ interface RowProps {
|
||||
unformatted?: boolean;
|
||||
assetSymbol?: string;
|
||||
noBorder?: boolean;
|
||||
parentValue?: ReactNode;
|
||||
hasParentData?: boolean;
|
||||
}
|
||||
|
||||
const Row = ({
|
||||
export const Row = ({
|
||||
field,
|
||||
value,
|
||||
decimalPlaces,
|
||||
@ -32,7 +36,14 @@ const Row = ({
|
||||
unformatted,
|
||||
assetSymbol = '',
|
||||
noBorder = true,
|
||||
parentValue,
|
||||
hasParentData,
|
||||
}: RowProps) => {
|
||||
// Note: we need both 'parentValue' and 'hasParentData' to do a conditional
|
||||
// check to differentiate between when parentData itself is missing and when
|
||||
// a specific parentValue is missing. These values are only used when we
|
||||
// have successor market parent data.
|
||||
|
||||
const className = 'text-sm';
|
||||
|
||||
const getFormattedValue = (value: ReactNode) => {
|
||||
@ -55,6 +66,10 @@ const Row = ({
|
||||
const formattedValue = getFormattedValue(value);
|
||||
|
||||
if (!formattedValue) return null;
|
||||
|
||||
const newValueInSuccessorMarket = hasParentData && value && !parentValue;
|
||||
const valueDiffersFromParentMarket = parentValue && parentValue !== value;
|
||||
|
||||
return (
|
||||
<KeyValueTableRow
|
||||
key={field}
|
||||
@ -63,10 +78,35 @@ const Row = ({
|
||||
dtClassName={className}
|
||||
ddClassName={className}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<Tooltip description={tooltipMapping[field]} align="start">
|
||||
<div tabIndex={-1}>{startCase(t(field))}</div>
|
||||
</Tooltip>
|
||||
<span style={{ wordBreak: 'break-word' }}>{formattedValue}</span>
|
||||
|
||||
{valueDiffersFromParentMarket && (
|
||||
<Lozenge className="py-0" variant={Intent.Primary}>
|
||||
{t('Updated')}
|
||||
</Lozenge>
|
||||
)}
|
||||
|
||||
{newValueInSuccessorMarket && (
|
||||
<Lozenge className="py-0" variant={Intent.Primary}>
|
||||
{t('Added')}
|
||||
</Lozenge>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ wordBreak: 'break-word' }}>
|
||||
{valueDiffersFromParentMarket ? (
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="line-through">
|
||||
{getFormattedValue(parentValue)}
|
||||
</span>
|
||||
<span>{formattedValue}</span>
|
||||
</div>
|
||||
) : (
|
||||
formattedValue
|
||||
)}
|
||||
</div>
|
||||
</KeyValueTableRow>
|
||||
);
|
||||
};
|
||||
@ -79,6 +119,7 @@ export interface MarketInfoTableProps {
|
||||
children?: ReactNode;
|
||||
assetSymbol?: string;
|
||||
noBorder?: boolean;
|
||||
parentData?: Record<string, ReactNode> | null | undefined;
|
||||
}
|
||||
|
||||
export const MarketInfoTable = ({
|
||||
@ -89,13 +130,18 @@ export const MarketInfoTable = ({
|
||||
children,
|
||||
assetSymbol,
|
||||
noBorder,
|
||||
parentData,
|
||||
}: MarketInfoTableProps) => {
|
||||
if (!data || typeof data !== 'object') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const hasParentData = parentData !== undefined;
|
||||
|
||||
return (
|
||||
<>
|
||||
<KeyValueTable>
|
||||
<>
|
||||
{Object.entries(data).map(([key, value]) => (
|
||||
<Row
|
||||
key={key}
|
||||
@ -106,8 +152,11 @@ export const MarketInfoTable = ({
|
||||
asPercentage={asPercentage}
|
||||
unformatted={unformatted}
|
||||
noBorder={noBorder}
|
||||
parentValue={parentData?.[key]}
|
||||
hasParentData={hasParentData}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
</KeyValueTable>
|
||||
<div className="flex flex-col gap-2">{children}</div>
|
||||
</>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import type { ReactNode } from 'react';
|
||||
import { Fragment, useState } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
@ -47,11 +48,14 @@ import {
|
||||
useSuccessorMarketQuery,
|
||||
} from '../../__generated__';
|
||||
import { useSuccessorMarketProposalDetailsQuery } from '@vegaprotocol/proposals';
|
||||
import type { MarketTradingMode } from '@vegaprotocol/types';
|
||||
import type { Signer } from '@vegaprotocol/types';
|
||||
import classNames from 'classnames';
|
||||
import compact from 'lodash/compact';
|
||||
|
||||
type MarketInfoProps = {
|
||||
market: MarketInfo;
|
||||
parentMarket?: MarketInfo;
|
||||
children?: ReactNode;
|
||||
};
|
||||
|
||||
@ -156,21 +160,43 @@ export const InsurancePoolInfoPanel = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const KeyDetailsInfoPanel = ({ market }: MarketInfoProps) => {
|
||||
const { data: parentData } = useParentMarketIdQuery({
|
||||
export const KeyDetailsInfoPanel = ({
|
||||
market,
|
||||
parentMarket,
|
||||
}: MarketInfoProps) => {
|
||||
const { data: parentMarketIdData } = useParentMarketIdQuery({
|
||||
variables: {
|
||||
marketId: market.id,
|
||||
},
|
||||
skip: !FLAGS.SUCCESSOR_MARKETS,
|
||||
});
|
||||
|
||||
const { data: successor } = useSuccessorMarketProposalDetailsQuery({
|
||||
const { data: successorProposalDetails } =
|
||||
useSuccessorMarketProposalDetailsQuery({
|
||||
variables: {
|
||||
proposalId: market.proposal?.id || '',
|
||||
},
|
||||
skip: !FLAGS.SUCCESSOR_MARKETS || !market.proposal?.id,
|
||||
});
|
||||
|
||||
// The following queries are needed as the parent market could also have been a successor market.
|
||||
// Note: the parent market is only passed to this component if the successor markets flag is enabled,
|
||||
// so that check is not needed in the skip.
|
||||
const { data: grandparentMarketIdData } = useParentMarketIdQuery({
|
||||
variables: {
|
||||
marketId: parentMarket?.id || '',
|
||||
},
|
||||
skip: !parentMarket?.id,
|
||||
});
|
||||
|
||||
const { data: parentSuccessorProposalDetails } =
|
||||
useSuccessorMarketProposalDetailsQuery({
|
||||
variables: {
|
||||
proposalId: parentMarket?.proposal?.id || '',
|
||||
},
|
||||
skip: !parentMarket?.proposal?.id,
|
||||
});
|
||||
|
||||
const assetDecimals =
|
||||
market.tradableInstrument.instrument.product.settlementAsset.decimals;
|
||||
|
||||
@ -181,11 +207,12 @@ export const KeyDetailsInfoPanel = ({ market }: MarketInfoProps) => {
|
||||
? {
|
||||
name: market.tradableInstrument.instrument.name,
|
||||
marketID: market.id,
|
||||
parentMarketID: parentData?.market?.parentMarketID || '-',
|
||||
parentMarketID: parentMarketIdData?.market?.parentMarketID || '-',
|
||||
insurancePoolFraction:
|
||||
(successor?.proposal?.terms.change.__typename === 'NewMarket' &&
|
||||
successor.proposal.terms.change.successorConfiguration
|
||||
?.insurancePoolFraction) ||
|
||||
(successorProposalDetails?.proposal?.terms.change.__typename ===
|
||||
'NewMarket' &&
|
||||
successorProposalDetails.proposal.terms.change
|
||||
.successorConfiguration?.insurancePoolFraction) ||
|
||||
'-',
|
||||
tradingMode:
|
||||
market.tradingMode &&
|
||||
@ -205,6 +232,28 @@ export const KeyDetailsInfoPanel = ({ market }: MarketInfoProps) => {
|
||||
settlementAssetDecimalPlaces: assetDecimals,
|
||||
}
|
||||
}
|
||||
parentData={
|
||||
parentMarket && {
|
||||
name: parentMarket?.tradableInstrument?.instrument?.name,
|
||||
marketID: parentMarket?.id,
|
||||
parentMarketID: grandparentMarketIdData?.market?.parentMarketID,
|
||||
insurancePoolFraction:
|
||||
parentSuccessorProposalDetails?.proposal?.terms.change
|
||||
.__typename === 'NewMarket' &&
|
||||
parentSuccessorProposalDetails.proposal.terms.change
|
||||
.successorConfiguration?.insurancePoolFraction,
|
||||
tradingMode:
|
||||
parentMarket?.tradingMode &&
|
||||
MarketTradingModeMapping[
|
||||
parentMarket.tradingMode as MarketTradingMode
|
||||
],
|
||||
marketDecimalPlaces: parentMarket?.decimalPlaces,
|
||||
positionDecimalPlaces: parentMarket?.positionDecimalPlaces,
|
||||
settlementAssetDecimalPlaces:
|
||||
parentMarket?.tradableInstrument?.instrument?.product
|
||||
?.settlementAsset?.decimals,
|
||||
}
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -329,7 +378,10 @@ export const SuccessionLineInfoPanel = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const InstrumentInfoPanel = ({ market }: MarketInfoProps) => (
|
||||
export const InstrumentInfoPanel = ({
|
||||
market,
|
||||
parentMarket,
|
||||
}: MarketInfoProps) => (
|
||||
<MarketInfoTable
|
||||
data={{
|
||||
marketName: market.tradableInstrument.instrument.name,
|
||||
@ -337,6 +389,16 @@ export const InstrumentInfoPanel = ({ market }: MarketInfoProps) => (
|
||||
productType: market.tradableInstrument.instrument.product.__typename,
|
||||
quoteName: market.tradableInstrument.instrument.product.quoteName,
|
||||
}}
|
||||
parentData={
|
||||
parentMarket && {
|
||||
marketName: parentMarket?.tradableInstrument?.instrument?.name,
|
||||
code: parentMarket?.tradableInstrument?.instrument?.code,
|
||||
productType:
|
||||
parentMarket?.tradableInstrument?.instrument?.product?.__typename,
|
||||
quoteName:
|
||||
parentMarket?.tradableInstrument?.instrument?.product?.quoteName,
|
||||
}
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -349,6 +411,7 @@ export const SettlementAssetInfoPanel = ({ market }: MarketInfoProps) => {
|
||||
() => market?.tradableInstrument.instrument.product?.settlementAsset.id,
|
||||
[market]
|
||||
);
|
||||
|
||||
const { data: asset } = useAssetDataProvider(assetId ?? '');
|
||||
return asset ? (
|
||||
<>
|
||||
@ -371,54 +434,148 @@ export const SettlementAssetInfoPanel = ({ market }: MarketInfoProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const MetadataInfoPanel = ({ market }: MarketInfoProps) => (
|
||||
const getMarketMetadata = (market: MarketInfo) =>
|
||||
market.tradableInstrument.instrument.metadata.tags
|
||||
?.map((tag) => {
|
||||
const [key, value] = tag.split(':');
|
||||
return { [key]: value };
|
||||
})
|
||||
.reduce((acc, curr) => ({ ...acc, ...curr }), {});
|
||||
|
||||
export const MetadataInfoPanel = ({
|
||||
market,
|
||||
parentMarket,
|
||||
}: MarketInfoProps) => (
|
||||
<MarketInfoTable
|
||||
data={{
|
||||
expiryDate: getMarketExpiryDateFormatted(
|
||||
market.tradableInstrument.instrument.metadata.tags
|
||||
),
|
||||
...market.tradableInstrument.instrument.metadata.tags
|
||||
?.map((tag) => {
|
||||
const [key, value] = tag.split(':');
|
||||
return { [key]: value };
|
||||
})
|
||||
.reduce((acc, curr) => ({ ...acc, ...curr }), {}),
|
||||
...(getMarketMetadata(market) || {}),
|
||||
}}
|
||||
parentData={
|
||||
parentMarket && {
|
||||
expiryDate: getMarketExpiryDateFormatted(
|
||||
parentMarket.tradableInstrument.instrument.metadata.tags
|
||||
),
|
||||
...(getMarketMetadata(parentMarket) || {}),
|
||||
}
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
export const RiskModelInfoPanel = ({ market }: MarketInfoProps) => {
|
||||
export const RiskModelInfoPanel = ({
|
||||
market,
|
||||
parentMarket,
|
||||
}: MarketInfoProps) => {
|
||||
if (market.tradableInstrument.riskModel.__typename !== 'LogNormalRiskModel') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { tau, riskAversionParameter } = market.tradableInstrument.riskModel;
|
||||
return <MarketInfoTable data={{ tau, riskAversionParameter }} unformatted />;
|
||||
|
||||
let parentData;
|
||||
|
||||
if (
|
||||
parentMarket?.tradableInstrument?.riskModel?.__typename ===
|
||||
'LogNormalRiskModel'
|
||||
) {
|
||||
const {
|
||||
tau: parentTau,
|
||||
riskAversionParameter: parentRiskAversionParameter,
|
||||
} = market.tradableInstrument.riskModel;
|
||||
|
||||
parentData = {
|
||||
tau: parentTau,
|
||||
riskAversionParameter: parentRiskAversionParameter,
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<MarketInfoTable
|
||||
data={{ tau, riskAversionParameter }}
|
||||
parentData={parentData}
|
||||
unformatted
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const RiskParametersInfoPanel = ({ market }: MarketInfoProps) => {
|
||||
if (market.tradableInstrument.riskModel.__typename === 'LogNormalRiskModel') {
|
||||
export const RiskParametersInfoPanel = ({
|
||||
market,
|
||||
parentMarket,
|
||||
}: MarketInfoProps) => {
|
||||
const marketType = market.tradableInstrument.riskModel.__typename;
|
||||
|
||||
let data, parentData;
|
||||
|
||||
if (marketType === 'LogNormalRiskModel') {
|
||||
const { r, sigma, mu } = market.tradableInstrument.riskModel.params;
|
||||
return <MarketInfoTable data={{ r, sigma, mu }} unformatted />;
|
||||
data = { r, sigma, mu };
|
||||
|
||||
if (
|
||||
parentMarket?.tradableInstrument?.riskModel.__typename ===
|
||||
'LogNormalRiskModel'
|
||||
) {
|
||||
const parentParams = parentMarket.tradableInstrument.riskModel.params;
|
||||
parentData = {
|
||||
r: parentParams.r,
|
||||
sigma: parentParams.sigma,
|
||||
mu: parentParams.mu,
|
||||
};
|
||||
}
|
||||
if (market.tradableInstrument.riskModel.__typename === 'SimpleRiskModel') {
|
||||
} else if (marketType === 'SimpleRiskModel') {
|
||||
const { factorLong, factorShort } =
|
||||
market.tradableInstrument.riskModel.params;
|
||||
return <MarketInfoTable data={{ factorLong, factorShort }} unformatted />;
|
||||
data = { factorLong, factorShort };
|
||||
|
||||
if (
|
||||
parentMarket?.tradableInstrument?.riskModel.__typename ===
|
||||
'SimpleRiskModel'
|
||||
) {
|
||||
const parentParams = parentMarket.tradableInstrument.riskModel.params;
|
||||
parentData = {
|
||||
factorLong: parentParams.factorLong,
|
||||
factorShort: parentParams.factorShort,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!data) return null;
|
||||
|
||||
return <MarketInfoTable data={data} parentData={parentData} unformatted />;
|
||||
};
|
||||
|
||||
export const RiskFactorsInfoPanel = ({ market }: MarketInfoProps) => {
|
||||
export const RiskFactorsInfoPanel = ({
|
||||
market,
|
||||
parentMarket,
|
||||
}: MarketInfoProps) => {
|
||||
if (!market.riskFactors) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { short, long } = market.riskFactors;
|
||||
return <MarketInfoTable data={{ short, long }} unformatted />;
|
||||
|
||||
let parentData;
|
||||
|
||||
if (parentMarket?.riskFactors) {
|
||||
const parentShort = parentMarket.riskFactors.short;
|
||||
const parentLong = parentMarket.riskFactors.long;
|
||||
parentData = { short: parentShort, long: parentLong };
|
||||
}
|
||||
|
||||
return (
|
||||
<MarketInfoTable
|
||||
data={{ short, long }}
|
||||
parentData={parentData}
|
||||
unformatted
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const PriceMonitoringBoundsInfoPanel = ({
|
||||
market,
|
||||
triggerIndex,
|
||||
parentMarket,
|
||||
}: MarketInfoProps & {
|
||||
triggerIndex: number;
|
||||
}) => {
|
||||
@ -426,11 +583,35 @@ export const PriceMonitoringBoundsInfoPanel = ({
|
||||
dataProvider: marketDataProvider,
|
||||
variables: { marketId: market.id },
|
||||
});
|
||||
|
||||
const { data: parentData } = useDataProvider({
|
||||
dataProvider: marketDataProvider,
|
||||
variables: { marketId: parentMarket?.id || '' },
|
||||
skip:
|
||||
!parentMarket ||
|
||||
!parentMarket?.priceMonitoringSettings?.parameters?.triggers?.[
|
||||
triggerIndex
|
||||
],
|
||||
});
|
||||
|
||||
const quoteUnit =
|
||||
market?.tradableInstrument.instrument.product?.quoteName || '';
|
||||
const parentQuoteUnit =
|
||||
parentMarket?.tradableInstrument.instrument.product?.quoteName || '';
|
||||
const isParentQuoteUnitEqual = quoteUnit === parentQuoteUnit;
|
||||
|
||||
const trigger =
|
||||
market.priceMonitoringSettings?.parameters?.triggers?.[triggerIndex];
|
||||
const parentTrigger =
|
||||
parentMarket?.priceMonitoringSettings?.parameters?.triggers?.[triggerIndex];
|
||||
const isParentTriggerEqual = isEqual(trigger, parentTrigger);
|
||||
|
||||
const bounds = data?.priceMonitoringBounds?.[triggerIndex];
|
||||
const parentBounds = parentData?.priceMonitoringBounds?.[triggerIndex];
|
||||
|
||||
const shouldShowParentData =
|
||||
isParentQuoteUnitEqual && isParentTriggerEqual && !!parentBounds;
|
||||
|
||||
if (!trigger) {
|
||||
console.error(
|
||||
`Could not find data for trigger ${triggerIndex} (market id: ${market.id})`
|
||||
@ -457,6 +638,14 @@ export const PriceMonitoringBoundsInfoPanel = ({
|
||||
highestPrice: bounds.maxValidPrice,
|
||||
lowestPrice: bounds.minValidPrice,
|
||||
}}
|
||||
parentData={
|
||||
shouldShowParentData
|
||||
? {
|
||||
highestPrice: parentBounds.maxValidPrice,
|
||||
lowestPrice: parentBounds.minValidPrice,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
decimalPlaces={market.decimalPlaces}
|
||||
assetSymbol={quoteUnit}
|
||||
/>
|
||||
@ -472,18 +661,31 @@ export const PriceMonitoringBoundsInfoPanel = ({
|
||||
|
||||
export const LiquidityMonitoringParametersInfoPanel = ({
|
||||
market,
|
||||
}: MarketInfoProps) => (
|
||||
<MarketInfoTable
|
||||
data={{
|
||||
parentMarket,
|
||||
}: MarketInfoProps) => {
|
||||
const marketData = {
|
||||
triggeringRatio: market.liquidityMonitoringParameters.triggeringRatio,
|
||||
timeWindow:
|
||||
market.liquidityMonitoringParameters.targetStakeParameters.timeWindow,
|
||||
scalingFactor:
|
||||
market.liquidityMonitoringParameters.targetStakeParameters
|
||||
market.liquidityMonitoringParameters.targetStakeParameters.scalingFactor,
|
||||
};
|
||||
|
||||
const parentMarketData = parentMarket
|
||||
? {
|
||||
triggeringRatio:
|
||||
parentMarket.liquidityMonitoringParameters.triggeringRatio,
|
||||
timeWindow:
|
||||
parentMarket.liquidityMonitoringParameters.targetStakeParameters
|
||||
.timeWindow,
|
||||
scalingFactor:
|
||||
parentMarket.liquidityMonitoringParameters.targetStakeParameters
|
||||
.scalingFactor,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
: {};
|
||||
|
||||
return <MarketInfoTable data={marketData} parentData={parentMarketData} />;
|
||||
};
|
||||
|
||||
export const LiquidityInfoPanel = ({ market, children }: MarketInfoProps) => {
|
||||
const assetDecimals =
|
||||
@ -510,16 +712,61 @@ export const LiquidityInfoPanel = ({ market, children }: MarketInfoProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const LiquidityPriceRangeInfoPanel = ({ market }: MarketInfoProps) => {
|
||||
export const LiquidityPriceRangeInfoPanel = ({
|
||||
market,
|
||||
parentMarket,
|
||||
}: MarketInfoProps) => {
|
||||
const quoteUnit =
|
||||
market?.tradableInstrument.instrument.product?.quoteName || '';
|
||||
const parentQuoteUnit =
|
||||
parentMarket?.tradableInstrument.instrument.product?.quoteName || '';
|
||||
|
||||
const liquidityPriceRange = formatNumberPercentage(
|
||||
new BigNumber(market.lpPriceRange).times(100)
|
||||
);
|
||||
const parentLiquidityPriceRange = parentMarket
|
||||
? formatNumberPercentage(
|
||||
new BigNumber(parentMarket.lpPriceRange).times(100)
|
||||
)
|
||||
: null;
|
||||
|
||||
const { data } = useDataProvider({
|
||||
dataProvider: marketDataProvider,
|
||||
variables: { marketId: market.id },
|
||||
});
|
||||
|
||||
const { data: parentMarketData } = useDataProvider({
|
||||
dataProvider: marketDataProvider,
|
||||
variables: { marketId: parentMarket?.id || '' },
|
||||
skip: !parentMarket,
|
||||
});
|
||||
|
||||
let parentData;
|
||||
|
||||
if (parentMarket && parentMarketData && quoteUnit === parentQuoteUnit) {
|
||||
parentData = {
|
||||
liquidityPriceRange: `${parentLiquidityPriceRange} of mid price`,
|
||||
lowestPrice:
|
||||
parentMarketData?.midPrice &&
|
||||
`${addDecimalsFormatNumber(
|
||||
new BigNumber(1)
|
||||
.minus(parentMarket.lpPriceRange)
|
||||
.times(parentMarketData.midPrice)
|
||||
.toString(),
|
||||
parentMarket.decimalPlaces
|
||||
)} ${quoteUnit}`,
|
||||
highestPrice:
|
||||
parentMarketData?.midPrice &&
|
||||
`${addDecimalsFormatNumber(
|
||||
new BigNumber(1)
|
||||
.plus(parentMarket.lpPriceRange)
|
||||
.times(parentMarketData.midPrice)
|
||||
.toString(),
|
||||
parentMarket.decimalPlaces
|
||||
)} ${quoteUnit}`,
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className="text-sm mb-2">
|
||||
@ -552,6 +799,7 @@ export const LiquidityPriceRangeInfoPanel = ({ market }: MarketInfoProps) => {
|
||||
market.decimalPlaces
|
||||
)} ${quoteUnit}`,
|
||||
}}
|
||||
parentData={parentData}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
@ -560,8 +808,12 @@ export const LiquidityPriceRangeInfoPanel = ({ market }: MarketInfoProps) => {
|
||||
export const OracleInfoPanel = ({
|
||||
market,
|
||||
type,
|
||||
parentMarket,
|
||||
}: MarketInfoProps & { type: 'settlementData' | 'termination' }) => {
|
||||
// If this is a successor market, this component will only receive parent market
|
||||
// data if the termination or settlement data is different from the parent.
|
||||
const product = market.tradableInstrument.instrument.product;
|
||||
const parentProduct = parentMarket?.tradableInstrument?.instrument?.product;
|
||||
const { VEGA_EXPLORER_URL, ORACLE_PROOFS_URL } = useEnvironment();
|
||||
const { data } = useOracleProofs(ORACLE_PROOFS_URL);
|
||||
|
||||
@ -570,12 +822,33 @@ export const OracleInfoPanel = ({
|
||||
? product.dataSourceSpecForSettlementData.id
|
||||
: product.dataSourceSpecForTradingTermination.id;
|
||||
|
||||
const parentDataSourceSpecId =
|
||||
type === 'settlementData'
|
||||
? parentProduct?.dataSourceSpecForSettlementData?.id
|
||||
: parentProduct?.dataSourceSpecForTradingTermination?.id;
|
||||
|
||||
const dataSourceSpec = (
|
||||
type === 'settlementData'
|
||||
? product.dataSourceSpecForSettlementData.data
|
||||
: product.dataSourceSpecForTradingTermination.data
|
||||
) as DataSourceDefinition;
|
||||
|
||||
const parentDataSourceSpec =
|
||||
type === 'settlementData'
|
||||
? parentProduct?.dataSourceSpecForSettlementData?.data
|
||||
: (parentProduct?.dataSourceSpecForTradingTermination
|
||||
?.data as DataSourceDefinition);
|
||||
|
||||
const isParentDataSourceSpecEqual =
|
||||
parentDataSourceSpec !== undefined &&
|
||||
dataSourceSpec === parentDataSourceSpec;
|
||||
const isParentDataSourceSpecIdEqual =
|
||||
parentDataSourceSpecId !== undefined &&
|
||||
dataSourceSpecId === parentDataSourceSpecId;
|
||||
|
||||
// We'll only provide successor parent data (if it differs) to the
|
||||
// DataSourceProof component. Having an old external link struck through
|
||||
// is unlikely to be useful.
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<DataSourceProof
|
||||
@ -584,7 +857,14 @@ export const OracleInfoPanel = ({
|
||||
providers={data}
|
||||
type={type}
|
||||
dataSourceSpecId={dataSourceSpecId}
|
||||
parentData={
|
||||
isParentDataSourceSpecEqual ? undefined : parentDataSourceSpec
|
||||
}
|
||||
parentDataSourceSpecId={
|
||||
isParentDataSourceSpecIdEqual ? undefined : parentDataSourceSpecId
|
||||
}
|
||||
/>
|
||||
|
||||
<ExternalLink
|
||||
data-testid="oracle-spec-links"
|
||||
href={`${VEGA_EXPLORER_URL}/oracles/${
|
||||
@ -606,14 +886,28 @@ export const DataSourceProof = ({
|
||||
providers,
|
||||
type,
|
||||
dataSourceSpecId,
|
||||
parentData,
|
||||
parentDataSourceSpecId,
|
||||
}: {
|
||||
data: DataSourceDefinition;
|
||||
providers: Provider[] | undefined;
|
||||
type: 'settlementData' | 'termination';
|
||||
dataSourceSpecId: string;
|
||||
parentData?: DataSourceDefinition;
|
||||
parentDataSourceSpecId?: string;
|
||||
}) => {
|
||||
// If this is a successor market, we'll only pass parent data to child
|
||||
// components for comparison if the data differs from the parent market.
|
||||
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
|
||||
const signers = data.sourceType.sourceType.signers || [];
|
||||
let parentSigners: Signer[];
|
||||
|
||||
if (
|
||||
parentData &&
|
||||
parentData.sourceType.__typename === 'DataSourceDefinitionExternal'
|
||||
) {
|
||||
parentSigners = parentData.sourceType.sourceType?.signers || [];
|
||||
}
|
||||
|
||||
if (!providers?.length) {
|
||||
return <NoOracleProof type={type} />;
|
||||
@ -622,7 +916,14 @@ export const DataSourceProof = ({
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
{signers.map(({ signer }, i) => {
|
||||
return (
|
||||
const parentSigner = parentSigners?.find(
|
||||
({ signer: ParentSigner }) =>
|
||||
ParentSigner.__typename === signer.__typename
|
||||
)?.signer;
|
||||
|
||||
const isParentSignerEqual = isEqual(signer, parentSigner);
|
||||
|
||||
return isParentSignerEqual ? (
|
||||
<OracleLink
|
||||
key={i}
|
||||
providers={providers}
|
||||
@ -630,6 +931,16 @@ export const DataSourceProof = ({
|
||||
type={type}
|
||||
dataSourceSpecId={dataSourceSpecId}
|
||||
/>
|
||||
) : (
|
||||
<OracleLink
|
||||
key={i}
|
||||
providers={providers}
|
||||
signer={signer}
|
||||
type={type}
|
||||
dataSourceSpecId={dataSourceSpecId}
|
||||
parentSigner={parentSigner}
|
||||
parentDataSourceSpecId={parentDataSourceSpecId}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
@ -663,18 +974,8 @@ export const DataSourceProof = ({
|
||||
return <div>{t('Invalid data source')}</div>;
|
||||
};
|
||||
|
||||
const OracleLink = ({
|
||||
providers,
|
||||
signer,
|
||||
type,
|
||||
dataSourceSpecId,
|
||||
}: {
|
||||
providers: Provider[];
|
||||
signer: SignerKind;
|
||||
type: 'settlementData' | 'termination';
|
||||
dataSourceSpecId: string;
|
||||
}) => {
|
||||
const signerProviders = providers.filter((p) => {
|
||||
const getSignerProviders = (signer: SignerKind, providers: Provider[]) =>
|
||||
providers.filter((p) => {
|
||||
if (signer.__typename === 'PubKey') {
|
||||
if (
|
||||
p.oracle.type === 'public_key' &&
|
||||
@ -696,19 +997,62 @@ const OracleLink = ({
|
||||
return false;
|
||||
});
|
||||
|
||||
const OracleLink = ({
|
||||
providers,
|
||||
signer,
|
||||
type,
|
||||
dataSourceSpecId,
|
||||
parentSigner,
|
||||
parentDataSourceSpecId,
|
||||
}: {
|
||||
providers: Provider[];
|
||||
signer: SignerKind;
|
||||
type: 'settlementData' | 'termination';
|
||||
dataSourceSpecId: string;
|
||||
parentSigner?: SignerKind;
|
||||
parentDataSourceSpecId?: string;
|
||||
}) => {
|
||||
// If this is a successor market, the parent market data will only have been passed
|
||||
// in if it differs from the current data.
|
||||
const signerProviders = getSignerProviders(signer, providers);
|
||||
const parentSignerProviders = parentSigner
|
||||
? getSignerProviders(parentSigner, providers)
|
||||
: [];
|
||||
|
||||
if (!signerProviders.length) {
|
||||
return <NoOracleProof type={type} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mt-2">
|
||||
{signerProviders.map((provider) => (
|
||||
{signerProviders.map((provider) => {
|
||||
// Making the assumption here that if the provider name is the same,
|
||||
// that it is the same provider that the parent market used.
|
||||
const parentProvider = parentSignerProviders.find(
|
||||
(p) => p.name === provider.name
|
||||
);
|
||||
|
||||
const isParentProviderEqual =
|
||||
parentProvider !== undefined && isEqual(provider, parentProvider);
|
||||
|
||||
// We only want to pass the parent data to the child component if the
|
||||
// data differs from the parent market.
|
||||
return isParentProviderEqual ? (
|
||||
<OracleProfile
|
||||
key={dataSourceSpecId}
|
||||
provider={provider}
|
||||
dataSourceSpecId={dataSourceSpecId}
|
||||
/>
|
||||
))}
|
||||
) : (
|
||||
<OracleProfile
|
||||
key={dataSourceSpecId}
|
||||
provider={provider}
|
||||
dataSourceSpecId={dataSourceSpecId}
|
||||
parentProvider={parentProvider}
|
||||
parentDataSourceSpecId={parentDataSourceSpecId}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -731,13 +1075,18 @@ const NoOracleProof = ({
|
||||
const OracleProfile = (props: {
|
||||
provider: Provider;
|
||||
dataSourceSpecId: string;
|
||||
parentProvider?: Provider;
|
||||
parentDataSourceSpecId?: string;
|
||||
}) => {
|
||||
// If this is a successor market, the parent market data will only have been passed
|
||||
// in if it differs from the current data.
|
||||
const [open, onChange] = useState(false);
|
||||
return (
|
||||
<div key={props.provider.name}>
|
||||
<OracleBasicProfile
|
||||
provider={props.provider}
|
||||
onClick={() => onChange(!open)}
|
||||
parentProvider={props.parentProvider}
|
||||
/>
|
||||
<OracleDialog {...props} open={open} onChange={onChange} />
|
||||
</div>
|
||||
|
@ -5,6 +5,7 @@ import {
|
||||
ExternalLink,
|
||||
Icon,
|
||||
Intent,
|
||||
Lozenge,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
@ -59,10 +60,12 @@ export const OracleBasicProfile = ({
|
||||
provider,
|
||||
onClick,
|
||||
markets: oracleMarkets,
|
||||
parentProvider,
|
||||
}: {
|
||||
provider: Provider;
|
||||
markets?: OracleMarketSpecFieldsFragment[] | undefined;
|
||||
onClick?: (value?: boolean) => void;
|
||||
parentProvider?: Provider;
|
||||
}) => {
|
||||
const { icon, message, intent } = getVerifiedStatusIcon(provider);
|
||||
|
||||
@ -78,8 +81,14 @@ export const OracleBasicProfile = ({
|
||||
icon: getLinkIcon(proof.type),
|
||||
}));
|
||||
|
||||
// If this is a successor market and there's a different parent provider,
|
||||
// we'll just show that there's been a change, rather than add old data
|
||||
// in alongside the new provider.
|
||||
return (
|
||||
<>
|
||||
{parentProvider && (
|
||||
<Lozenge variant={Intent.Primary}>{t('Updated')}</Lozenge>
|
||||
)}
|
||||
<span className="flex gap-1">
|
||||
{provider.url && (
|
||||
<span className="flex align-items-bottom text-md gap-1">
|
||||
|
@ -11,16 +11,27 @@ export const OracleDialog = ({
|
||||
dataSourceSpecId,
|
||||
open,
|
||||
onChange,
|
||||
parentProvider,
|
||||
}: {
|
||||
dataSourceSpecId: string;
|
||||
provider: Provider;
|
||||
open: boolean;
|
||||
onChange?: (isOpen: boolean) => void;
|
||||
parentProvider?: Provider;
|
||||
}) => {
|
||||
// If this is a successor market, the parent market data will only have been passed
|
||||
// in if it differs from the current data. We'll pass this on to the title component
|
||||
// to show a change, but the full profile showing changes is unwieldy - it's enough
|
||||
// to know from the title that the oracle has changed.
|
||||
const oracleMarkets = useOracleMarkets(provider);
|
||||
return (
|
||||
<Dialog
|
||||
title={<OracleProfileTitle provider={provider} />}
|
||||
title={
|
||||
<OracleProfileTitle
|
||||
provider={provider}
|
||||
parentProvider={parentProvider}
|
||||
/>
|
||||
}
|
||||
aria-labelledby="oracle-proof-dialog"
|
||||
open={open}
|
||||
onChange={onChange}
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
ExternalLink,
|
||||
Icon,
|
||||
Intent,
|
||||
Lozenge,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
@ -18,15 +19,30 @@ import type { OracleMarketSpecFieldsFragment } from '../../__generated__/OracleM
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import { useState } from 'react';
|
||||
|
||||
export const OracleProfileTitle = ({ provider }: { provider: Provider }) => {
|
||||
export const OracleProfileTitle = ({
|
||||
provider,
|
||||
parentProvider,
|
||||
}: {
|
||||
provider: Provider;
|
||||
parentProvider?: Provider;
|
||||
}) => {
|
||||
// If this is a successor market, the parent provider will only have been passed
|
||||
// in if it differs from the current provider. If it is different, we'll just
|
||||
// show the change in name, not icons and proofs.
|
||||
const { icon, intent } = getVerifiedStatusIcon(provider);
|
||||
const verifiedProofs = provider.proofs.filter(
|
||||
(proof) => proof.available === true
|
||||
);
|
||||
return (
|
||||
<span className="flex gap-1">
|
||||
{parentProvider && (
|
||||
<Lozenge variant={Intent.Primary}>{t('Updated')}</Lozenge>
|
||||
)}
|
||||
{provider.url && (
|
||||
<span>
|
||||
{parentProvider && parentProvider.name && (
|
||||
<span className="line-through">{parentProvider.name}</span>
|
||||
)}
|
||||
<span className="pr-1">{provider.name}</span>
|
||||
<span className="dark:text-vega-light-300 text-vega-dark-300">
|
||||
({verifiedProofs.length})
|
||||
|
@ -22,7 +22,7 @@ export const getIntentBackground = (intent?: Intent) => {
|
||||
return {
|
||||
'bg-neutral-200 dark:bg-neutral-800': intent === undefined,
|
||||
'bg-black dark:bg-white': intent === Intent.None,
|
||||
'bg-vega-blue-300 dark:bg-vega-blue-700': intent === Intent.Primary,
|
||||
'bg-vega-blue-300 dark:bg-vega-blue-650': intent === Intent.Primary,
|
||||
'bg-danger': intent === Intent.Danger,
|
||||
'bg-warning': intent === Intent.Warning,
|
||||
// contrast issues with light mode
|
||||
|
Loading…
Reference in New Issue
Block a user