Compare commits

...
23 changed files with 138 additions and 235 deletions
@@ -0,0 +1,44 @@
import {
useLinks,
DApp,
CONSOLE_REWARDS_PAGE,
} from '@vegaprotocol/environment';
import {
ExternalLink,
Intent,
NotificationBanner,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import { Trans } from 'react-i18next';
import { useMatch } from 'react-router-dom';
import Routes from '../../routes/routes';
import { type ReactNode } from 'react';
const ConsoleRewardsLink = ({ children }: { children: ReactNode }) => {
const consoleLink = useLinks(DApp.Console);
return (
<ExternalLink
href={consoleLink(CONSOLE_REWARDS_PAGE)}
className="underline inline-flex gap-1 items-center"
title="Rewards in Console"
>
<span>{children}</span>
<VegaIcon size={12} name={VegaIconNames.OPEN_EXTERNAL} />
</ExternalLink>
);
};
export const RewardsMovedNotification = () => {
const onRewardsPage = useMatch(Routes.REWARDS);
if (!onRewardsPage) return null;
return (
<NotificationBanner intent={Intent.Warning}>
<Trans
i18nKey="rewardsMovedNotification"
components={[<ConsoleRewardsLink>Console</ConsoleRewardsLink>]}
/>
</NotificationBanner>
);
};
@@ -10,6 +10,7 @@ import {
ProtocolUpgradeProposalNotification,
} from '@vegaprotocol/proposals';
import { ViewingAsBanner } from '@vegaprotocol/ui-toolkit';
import { RewardsMovedNotification } from '../notifications/rewards-moved-notification';
interface AppLayoutProps {
children: ReactNode;
@@ -45,8 +46,10 @@ export const AppLayout = ({ children }: AppLayoutProps) => {
const NotificationsContainer = () => {
const { isReadOnly, pubKey, disconnect } = useVegaWallet();
return (
<div data-testid="banners">
<RewardsMovedNotification />
<ProtocolUpgradeProposalNotification
mode={ProtocolUpgradeCountdownMode.IN_ESTIMATED_TIME_REMAINING}
/>
@@ -288,7 +288,7 @@ describe('Consensus validators table', () => {
expect(
grid.querySelector('[role="gridcell"][col-id="totalPenalties"]')
).toHaveTextContent('13.16%');
).toHaveTextContent('10.07%');
expect(
grid.querySelector('[role="gridcell"][col-id="normalisedVotingPower"]')
@@ -185,15 +185,19 @@ export const ConsensusValidatorsTable = ({
const { rawValidatorScore: previousEpochValidatorScore } =
getLastEpochScoreAndPerformance(previousEpochData, id);
const overstakingPenalty = calculateOverallPenalty(
const overstakingPenalty = calculateOverstakedPenalty(
id,
allNodesInPreviousEpoch
);
const totalPenalty = calculateOverstakedPenalty(
const totalPenalty = calculateOverallPenalty(
id,
allNodesInPreviousEpoch
);
const lastEpochDataForNode = allNodesInPreviousEpoch.find(
(node) => node.id === id
);
return {
id,
[ValidatorFields.RANKING_INDEX]: stakedTotalRanking,
@@ -239,6 +243,12 @@ export const ConsensusValidatorsTable = ({
: undefined,
[ValidatorFields.MULTISIG_ERROR]:
multisigStatus?.showMultisigStatusError,
[ValidatorFields.MULTISIG_PENALTY]: formatNumberPercentage(
new BigNumber(1)
.minus(lastEpochDataForNode?.rewardScore?.multisigScore ?? 1)
.times(100),
2
),
};
}
);
@@ -378,7 +388,6 @@ export const ConsensusValidatorsTable = ({
headerTooltip: t('StakeDescription').toString(),
cellRenderer: TotalStakeRenderer,
width: 120,
sort: 'desc',
},
{
field: ValidatorFields.PENDING_STAKE,
@@ -400,6 +409,7 @@ export const ConsensusValidatorsTable = ({
headerTooltip: t('NormalisedVotingPowerDescription').toString(),
cellRenderer: VotingPowerRenderer,
width: 120,
sort: 'desc',
},
{
field: ValidatorFields.TOTAL_PENALTIES,
@@ -40,6 +40,7 @@ export enum ValidatorFields {
PENDING_USER_STAKE = 'pendingUserStake',
USER_STAKE_SHARE = 'userStakeShare',
MULTISIG_ERROR = 'multisigError',
MULTISIG_PENALTY = 'multisigPenalty',
}
export const addUserDataToValidator = (
@@ -327,7 +328,7 @@ interface TotalPenaltiesRendererProps {
overstakedAmount: string;
overstakingPenalty: string;
totalPenalties: string;
multisigError?: boolean;
multisigPenalty: string;
};
}
@@ -346,11 +347,9 @@ export const TotalPenaltiesRenderer = ({
<div data-testid="overstaked-penalty-tooltip">
{t('overstakedPenalty')}: {data.overstakingPenalty}
</div>
{data.multisigError && (
<div data-testid="multisig-error-tooltip">
{t('multisigPenalty')}: 100%
</div>
)}
<div data-testid="multisig-error-tooltip">
{t('multisigPenalty')}: {data.multisigPenalty}
</div>
</>
}
>
@@ -37,7 +37,6 @@ import {
import type { ReactNode } from 'react';
import type { StakingNodeFieldsFragment } from '../__generated__/Staking';
import type { PreviousEpochQuery } from '../__generated__/PreviousEpoch';
import { getMultisigStatusInfo } from '../../../lib/get-multisig-status-info';
const statuses = {
[Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_ERSATZ]: 'status-ersatz',
@@ -105,9 +104,10 @@ export const ValidatorTable = ({
};
}, [node, previousEpochData?.epoch.validatorsConnection?.edges]);
const multisigStatus = previousEpochData
? getMultisigStatusInfo(previousEpochData)
: undefined;
const previousNodeData =
previousEpochData?.epoch.validatorsConnection?.edges?.find(
(e) => e?.node.id === node.id
);
return (
<>
@@ -293,21 +293,15 @@ export const ValidatorTable = ({
data-testid="multisig-penalty"
className="flex gap-2 items-baseline"
>
{multisigStatus?.zeroScoreNodes.find(
(n) => n.id === node.id
) ? (
<Tooltip
description={t('multisigPenaltyThisNodeIndicator')}
>
<span className="inline-block w-2 h-2 rounded-full bg-vega-red-500"></span>
</Tooltip>
) : null}
<Tooltip description={t('multisigPenaltyDescription')}>
<span>
{formatNumberPercentage(
BigNumber(
multisigStatus?.showMultisigStatusError ? 100 : 0
),
new BigNumber(1)
.minus(
previousNodeData?.node.rewardScore?.multisigScore ??
1
)
.times(100),
2
)}
</span>
@@ -30,8 +30,6 @@ export const ChartContainer = ({ marketId }: { marketId: string }) => {
setStudies,
setStudySizes,
setOverlays,
state,
setState,
} = useChartSettings();
const pennantChart = (
@@ -68,10 +66,6 @@ export const ChartContainer = ({ marketId }: { marketId: string }) => {
onIntervalChange={(newInterval) => {
setInterval(fromTradingViewResolution(newInterval));
}}
onAutoSaveNeeded={(data) => {
setState(data);
}}
state={state}
/>
);
}
@@ -9,7 +9,6 @@ type StudySizes = { [S in Study]?: number };
export type Chartlib = 'pennant' | 'tradingview';
interface StoredSettings {
state: object | undefined; // Don't see a better type provided from TradingView type definitions
chartlib: Chartlib;
// For interval we use the enum from @vegaprotocol/types, this is to make mapping between different
// chart types easier and more consistent
@@ -30,7 +29,6 @@ const STUDY_ORDER: Study[] = [
];
export const DEFAULT_CHART_SETTINGS = {
state: undefined,
chartlib: 'pennant' as const,
interval: Interval.INTERVAL_I15M,
type: ChartType.CANDLE,
@@ -47,7 +45,6 @@ export const useChartSettingsStore = create<
setStudies: (studies?: Study[]) => void;
setStudySizes: (sizes: number[]) => void;
setChartlib: (lib: Chartlib) => void;
setState: (state: object) => void;
}
>()(
persist(
@@ -95,9 +92,6 @@ export const useChartSettingsStore = create<
state.chartlib = lib;
});
},
setState: (state) => {
set({ state });
},
})),
{
name: 'vega_candles_chart_store',
@@ -151,7 +145,5 @@ export const useChartSettings = () => {
setOverlays: settings.setOverlays,
setStudySizes: settings.setStudySizes,
setChartlib: settings.setChartlib,
state: settings.state,
setState: settings.setState,
};
};
@@ -77,7 +77,7 @@ def test_market_info_market_volume(page: Page):
page.get_by_test_id(market_title_test_id).get_by_text(
"Market volume").click()
fields = [
["24 Hour Volume", "-"],
["24 Hour Volume", "0 (0 )"],
["Open Interest", "1"],
["Best Bid Volume", "99"],
["Best Offer Volume", "99"],
+7
View File
@@ -62,3 +62,10 @@ export const DENY_LIST: Record<string, string[]> = {
'fdf0ec118d98393a7702cf72e46fc87ad680b152f64b2aac59e093ac2d688fbb',
],
};
// We need a record of USDT on mainnet as it needs special handling for
// deposits and approvals due to the contract not conforming exactly
// to ERC20
export const USDT_ID = {
MAINNET: 'bf1e88d19db4b3ca0d1d5bdb73718a01686b18cf731ca26adedf3c8b83802bba',
} as const;
+37 -15
View File
@@ -1,5 +1,9 @@
import type { Asset } from '@vegaprotocol/assets';
import { EtherscanLink } from '@vegaprotocol/environment';
import { USDT_ID, type Asset } from '@vegaprotocol/assets';
import {
EtherscanLink,
Networks,
useEnvironment,
} from '@vegaprotocol/environment';
import { Intent, Notification } from '@vegaprotocol/ui-toolkit';
import {
formatNumber,
@@ -15,7 +19,7 @@ import { useT } from './use-t';
interface ApproveNotificationProps {
isActive: boolean;
selectedAsset?: Asset;
onApprove: () => void;
onApprove: (amount?: string) => void;
approved: boolean;
balances: DepositBalances | null;
amount: string;
@@ -33,6 +37,7 @@ export const ApproveNotification = ({
approveTxId,
intent = Intent.Warning,
}: ApproveNotificationProps) => {
const { VEGA_ENV } = useEnvironment();
const t = useT();
const tx = useEthTransactionStore((state) => {
return state.transactions.find((t) => t?.id === approveTxId);
@@ -64,28 +69,45 @@ export const ApproveNotification = ({
text: t('Approve {{assetSymbol}}', {
assetSymbol: selectedAsset?.symbol,
}),
action: onApprove,
action: () => onApprove(),
dataTestId: 'approve-submit',
}}
/>
</div>
);
let message = t('Approve again to deposit more than {{allowance}}', {
allowance: formatNumber(balances.allowance.toString()),
});
const buttonProps = {
size: 'small' as const,
text: t('Approve {{assetSymbol}}', {
assetSymbol: selectedAsset?.symbol,
}),
action: () => onApprove(),
dataTestId: 'reapprove-submit',
};
if (VEGA_ENV === Networks.MAINNET && selectedAsset.id === USDT_ID[VEGA_ENV]) {
message = t(
'USDT approved amount cannot be changed, only revoked. Revoke and reapprove to deposit more than {{allowance}}.',
{
allowance: formatNumber(balances.allowance.toString()),
}
);
buttonProps.text = t('Revoke {{assetSymbol}} approval', {
assetSymbol: selectedAsset?.symbol,
});
buttonProps.action = () => onApprove('0');
}
const reApprovePrompt = (
<div className="mb-4">
<Notification
intent={intent}
testId="reapprove-default"
message={t('Approve again to deposit more than {{allowance}}', {
allowance: formatNumber(balances.allowance.toString()),
})}
buttonProps={{
size: 'small',
text: t('Approve {{assetSymbol}}', {
assetSymbol: selectedAsset?.symbol,
}),
action: onApprove,
dataTestId: 'reapprove-submit',
}}
message={message}
buttonProps={buttonProps}
/>
</div>
);
+3 -3
View File
@@ -58,7 +58,7 @@ export interface DepositFormProps {
onSelectAsset: (assetId: string) => void;
handleAmountChange: (amount: string) => void;
onDisconnect: () => void;
submitApprove: () => void;
submitApprove: (amount?: string) => void;
approveTxId: number | null;
submitFaucet: () => void;
faucetTxId: number | null;
@@ -423,8 +423,8 @@ export const DepositForm = ({
isActive={isActive}
approveTxId={approveTxId}
selectedAsset={selectedAsset}
onApprove={() => {
submitApprove();
onApprove={(amount) => {
submitApprove(amount);
setApproveNotificationIntent(Intent.Warning);
}}
balances={balances}
+2 -2
View File
@@ -35,11 +35,11 @@ export const useSubmitApproval = (
reset: () => {
setId(null);
},
perform: () => {
perform: (amount?: string) => {
if (!asset || !config) return;
const id = createEthTransaction(contract, 'approve', [
config?.collateral_bridge_contract.address,
MaxUint256.toString(),
amount ? amount : MaxUint256.toString(),
]);
setId(id);
},
+1
View File
@@ -134,6 +134,7 @@ export const CONSOLE_TRANSFER = '#/portfolio/assets/transfer';
export const CONSOLE_TRANSFER_ASSET =
'#/portfolio/assets/transfer?assetId=:assetId';
export const CONSOLE_MARKET_PAGE = '#/markets/:marketId';
export const CONSOLE_REWARDS_PAGE = '#/rewards';
// Governance pages
export const TOKEN_NEW_MARKET_PROPOSAL = '/proposals/propose/new-market';
+2
View File
@@ -4,6 +4,7 @@
"Approval failed": "Approval failed",
"Approve {{assetSymbol}}": "Approve {{assetSymbol}}",
"Approve again to deposit more than {{allowance}}": "Approve again to deposit more than {{allowance}}",
"USDT approved amount cannot be changed, only revoked. Revoke and reapprove to deposit more than {{allowance}}.": "USDT approved amount cannot be changed, only revoked. Revoke and reapprove to deposit more than {{allowance}}.",
"Asset": "Asset",
"Balance available": "Balance available",
"Before you can make a deposit of your chosen asset, {{assetSymbol}}, you need to approve its use in your Ethereum wallet": "Before you can make a deposit of your chosen asset, {{assetSymbol}}, you need to approve its use in your Ethereum wallet",
@@ -23,6 +24,7 @@
"Please select": "Please select",
"Please select an asset": "Please select an asset",
"Remaining deposit allowance": "Remaining deposit allowance",
"Revoke {{assetSymbol}} approval": "Revoke {{assetSymbol}} approval",
"Select from wallet": "Select from wallet",
"The {{symbol}} faucet is not available at this time": "The {{symbol}} faucet is not available at this time",
"The deposit cap is set when you approve an asset for use with this app. To increase this cap, approve {{assetSymbol}} again and choose a higher cap. Check the documentation for your Ethereum wallet app for details.": "The deposit cap is set when you approve an asset for use with this app. To increase this cap, approve {{assetSymbol}} again and choose a higher cap. Check the documentation for your Ethereum wallet app for details.",
+2 -1
View File
@@ -969,5 +969,6 @@
"YourIdentityAnonymous": "Your identity is always anonymous on Vega",
"yourStake": "Your stake",
"yourVote": "Your vote",
"youVoted": "You voted"
"youVoted": "You voted",
"rewardsMovedNotification": "Trading and liquidity rewards have moved. Visit <0>Console</0> to view your rewards."
}
-5
View File
@@ -1,8 +1,6 @@
{
"{{liquidityPriceRange}} of mid price": "{{liquidityPriceRange}} of mid price",
"{{probability}} probability price bounds": "{{probability}} probability price bounds",
"24 hour change is unavailable at this time. The price change in the last 120 hours is:": "24 hour change is unavailable at this time. The price change in the last 120 hours is:",
"24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}": "24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}",
"A concept derived from traditional markets. It is a calculated value for the current market price on a market.": "A concept derived from traditional markets. It is a calculated value for the current market price on a market.",
"A number that will be calculated by an appropriate stochastic risk model, dependent on the type of risk model used and its parameters.": "A number that will be calculated by an appropriate stochastic risk model, dependent on the type of risk model used and its parameters.",
"A sliding penalty for how much an LP bond is slashed if an LP fails to reach the minimum SLA. This is a network parameter.": "A sliding penalty for how much an LP bond is slashed if an LP fails to reach the minimum SLA. This is a network parameter.",
@@ -51,9 +49,6 @@
"Market": "Market",
"Market data": "Market data",
"Market governance": "Market governance",
"Market has not been active for 24 hours. The price change between {{start}} and {{end}} is:": "Market has not been active for 24 hours. The price change between {{start}} and {{end}} is:",
"Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is:": "Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is:",
"Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}": "Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}",
"Market ID": "Market ID",
"Market price": "Market price",
"Market specification": "Market specification",
@@ -2,16 +2,14 @@ import { type ReactNode } from 'react';
import {
addDecimalsFormatNumber,
formatNumberPercentage,
getDateTimeFormat,
priceChange,
priceChangePercentage,
} from '@vegaprotocol/utils';
import { PriceChangeCell, signedNumberCssClass } from '@vegaprotocol/datagrid';
import { Tooltip, VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
import { signedNumberCssClass } from '@vegaprotocol/datagrid';
import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
import { useCandles } from '../../hooks/use-candles';
import BigNumber from 'bignumber.js';
import classNames from 'classnames';
import { useT } from '../../use-t';
interface Props {
marketId?: string;
@@ -24,7 +22,6 @@ export const Last24hPriceChange = ({
decimalPlaces,
fallback,
}: Props) => {
const t = useT();
const { oneDayCandles, fiveDaysCandles, error } = useCandles({
marketId,
});
@@ -35,56 +32,6 @@ export const Last24hPriceChange = ({
return nonIdeal;
}
if (fiveDaysCandles.length < 24) {
return (
<Tooltip
description={
<span className="justify-start">
{t(
'Market has not been active for 24 hours. The price change between {{start}} and {{end}} is:',
{
start: getDateTimeFormat().format(
new Date(fiveDaysCandles[0].periodStart)
),
end: getDateTimeFormat().format(
new Date(
fiveDaysCandles[fiveDaysCandles.length - 1].periodStart
)
),
}
)}
<PriceChangeCell
candles={fiveDaysCandles.map((c) => c.close) || []}
decimalPlaces={decimalPlaces}
/>
</span>
}
>
<span>{nonIdeal}</span>
</Tooltip>
);
}
if (oneDayCandles.length < 24) {
return (
<Tooltip
description={
<span className="justify-start">
{t(
'24 hour change is unavailable at this time. The price change in the last 120 hours is:'
)}{' '}
<PriceChangeCell
candles={fiveDaysCandles.map((c) => c.close) || []}
decimalPlaces={decimalPlaces}
/>
</span>
}
>
<span>{nonIdeal}</span>
</Tooltip>
);
}
const candles = oneDayCandles?.map((c) => c.close) || [];
const change = priceChange(candles);
const changePercentage = priceChangePercentage(candles);
@@ -2,7 +2,6 @@ import { calcCandleVolume, calcCandleVolumePrice } from '../../market-utils';
import {
addDecimalsFormatNumber,
formatNumber,
getDateTimeFormat,
isNumeric,
} from '@vegaprotocol/utils';
import { Tooltip } from '@vegaprotocol/ui-toolkit';
@@ -37,83 +36,6 @@ export const Last24hVolume = ({
return nonIdeal;
}
if (fiveDaysCandles.length < 24) {
const candleVolume = calcCandleVolume(fiveDaysCandles);
const candleVolumePrice = calcCandleVolumePrice(
fiveDaysCandles,
marketDecimals,
positionDecimalPlaces
);
const candleVolumeValue =
candleVolume && isNumeric(positionDecimalPlaces)
? addDecimalsFormatNumber(
candleVolume,
positionDecimalPlaces,
formatDecimals
)
: '-';
return (
<Tooltip
description={
<div>
<span className="flex flex-col">
{t(
'Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}',
{
start: getDateTimeFormat().format(
new Date(fiveDaysCandles[0].periodStart)
),
end: getDateTimeFormat().format(
new Date(
fiveDaysCandles[fiveDaysCandles.length - 1].periodStart
)
),
candleVolumeValue,
candleVolumePrice,
quoteUnit,
}
)}
</span>
</div>
}
>
<span>{nonIdeal}</span>
</Tooltip>
);
}
if (oneDayCandles.length < 24) {
const candleVolume = calcCandleVolume(fiveDaysCandles);
const candleVolumePrice = calcCandleVolumePrice(
fiveDaysCandles,
marketDecimals,
positionDecimalPlaces
);
const candleVolumeValue =
candleVolume && isNumeric(positionDecimalPlaces)
? addDecimalsFormatNumber(
candleVolume,
positionDecimalPlaces,
formatDecimals
)
: '-';
return (
<Tooltip
description={
<div>
<span className="flex flex-col">
{t(
'24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}} for a total of ({{candleVolumePrice}} {{quoteUnit}})',
{ candleVolumeValue, candleVolumePrice, quoteUnit }
)}
</span>
</div>
}
>
<span>{nonIdeal}</span>
</Tooltip>
);
}
const candleVolume = oneDayCandles
? calcCandleVolume(oneDayCandles)
: initialValue;
+1 -8
View File
@@ -8,7 +8,7 @@ export const useCandles = ({ marketId }: { marketId?: string }) => {
const fiveDaysAgo = useFiveDaysAgo();
const yesterday = useYesterday();
const since = new Date(fiveDaysAgo).toISOString();
const { data, error } = useThrottledDataProvider({
const { data: fiveDaysCandles, error } = useThrottledDataProvider({
dataProvider: marketCandlesProvider,
variables: {
marketId: marketId || '',
@@ -18,13 +18,6 @@ export const useCandles = ({ marketId }: { marketId?: string }) => {
skip: !marketId,
});
const fiveDaysCandles = data?.filter((c) => {
if (c.open === '' || c.close === '' || c.high === '' || c.close === '') {
return false;
}
return true;
});
const oneDayCandles = fiveDaysCandles?.filter((candle) =>
isCandleLessThan24hOld(candle, yesterday)
);
@@ -1,7 +1,7 @@
import { useScript } from '@vegaprotocol/react-helpers';
import { Splash } from '@vegaprotocol/ui-toolkit';
import { useT } from './use-t';
import { TradingView, type OnAutoSaveNeededCallback } from './trading-view';
import { TradingView } from './trading-view';
import { CHARTING_LIBRARY_FILE, type ResolutionString } from './constants';
export const TradingViewContainer = ({
@@ -10,16 +10,12 @@ export const TradingViewContainer = ({
marketId,
interval,
onIntervalChange,
onAutoSaveNeeded,
state,
}: {
libraryPath: string;
libraryHash: string;
marketId: string;
interval: ResolutionString;
onIntervalChange: (interval: string) => void;
onAutoSaveNeeded: OnAutoSaveNeededCallback;
state: object | undefined;
}) => {
const t = useT();
const scriptState = useScript(
@@ -49,8 +45,6 @@ export const TradingViewContainer = ({
marketId={marketId}
interval={interval}
onIntervalChange={onIntervalChange}
onAutoSaveNeeded={onAutoSaveNeeded}
state={state}
/>
);
};
+1 -20
View File
@@ -25,15 +25,11 @@ export const TradingView = ({
libraryPath,
interval,
onIntervalChange,
onAutoSaveNeeded,
state,
}: {
marketId: string;
libraryPath: string;
interval: ResolutionString;
onIntervalChange: (interval: string) => void;
onAutoSaveNeeded: OnAutoSaveNeededCallback;
state: object | undefined;
}) => {
const { isMobile } = useScreenDimensions();
const { theme } = useThemeSwitcher();
@@ -108,7 +104,6 @@ export const TradingView = ({
backgroundColor: overrides['paneProperties.background'],
},
auto_save_delay: 1,
saved_data: state,
};
widgetRef.current = new window.TradingView.widget(widgetOptions);
@@ -117,25 +112,12 @@ export const TradingView = ({
if (!widgetRef.current) return;
const activeChart = widgetRef.current.activeChart();
if (!state) {
// If chart has loaded with no state, create a volume study
activeChart.createStudy('Volume');
}
activeChart.createStudy('Volume');
// Subscribe to interval changes so it can be persisted in chart settings
activeChart.onIntervalChanged().subscribe(null, onIntervalChange);
});
widgetRef.current.subscribe('onAutoSaveNeeded', () => {
if (!widgetRef.current) return;
widgetRef.current.save((newState) => {
onAutoSaveNeeded(newState);
});
});
}, [
state,
datafeed,
interval,
prevTheme,
@@ -145,7 +127,6 @@ export const TradingView = ({
language,
libraryPath,
isMobile,
onAutoSaveNeeded,
onIntervalChange,
]);
@@ -27,6 +27,7 @@ export const useEthTransactionManager = () => {
confirmations: 0,
notify: true,
});
const {
contract,
methodName,
@@ -44,6 +45,7 @@ export const useEthTransactionManager = () => {
) {
throw new Error('method not found on contract');
}
await contract.contract.callStatic[methodName](...args);
} catch (err) {
update(transaction.id, {