Compare commits

...

3 Commits

Author SHA1 Message Date
Bill He
8c3f867f06
Learnmore -> LearnMore 2023-10-31 10:58:33 -07:00
Bill He
1a95814925
add learnmore to tooltip 2023-10-31 10:57:21 -07:00
Bill He
a6d7a5cb4e
Configurable URLs 2023-10-31 10:57:20 -07:00
13 changed files with 265 additions and 83 deletions

View File

@ -71,7 +71,19 @@
"tos": "https://dydx.exchange/v4-terms", "tos": "https://dydx.exchange/v4-terms",
"privacy": "https://dydx.exchange/privacy", "privacy": "https://dydx.exchange/privacy",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}", "mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"governanceLearnMore": "https://help.dydx.exchange",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"accountExportLearnMore": "https://help.dydx.exchange",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -130,7 +142,19 @@
"tos": "https://dydx.exchange/v4-terms", "tos": "https://dydx.exchange/v4-terms",
"privacy": "https://dydx.exchange/privacy", "privacy": "https://dydx.exchange/privacy",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}", "mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"governanceLearnMore": "https://help.dydx.exchange",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"accountExportLearnMore": "https://help.dydx.exchange",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -189,7 +213,19 @@
"tos": "https://dydx.exchange/v4-terms", "tos": "https://dydx.exchange/v4-terms",
"privacy": "https://dydx.exchange/privacy", "privacy": "https://dydx.exchange/privacy",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}", "mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"governanceLearnMore": "https://help.dydx.exchange",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"accountExportLearnMore": "https://help.dydx.exchange",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -248,7 +284,19 @@
"tos": "https://dydx.exchange/v4-terms", "tos": "https://dydx.exchange/v4-terms",
"privacy": "https://dydx.exchange/privacy", "privacy": "https://dydx.exchange/privacy",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}", "mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"governanceLearnMore": "https://help.dydx.exchange",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"accountExportLearnMore": "https://help.dydx.exchange",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -312,7 +360,16 @@
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog", "blogs": "https://www.dydx.foundation/blog",
"help": "https://help.dydx.exchange" "help": "https://help.dydx.exchange",
"foundation": "https://www.dydx.foundation",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"accountExportLearnMore": "https://help.dydx.exchange",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -376,7 +433,16 @@
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog", "blogs": "https://www.dydx.foundation/blog",
"help": "https://help.dydx.exchange" "help": "https://help.dydx.exchange",
"foundation": "https://www.dydx.foundation",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"accountExportLearnMore": "https://help.dydx.exchange",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -443,7 +509,17 @@
"documentation": "https://docs.dydx.exchange/", "documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"accountExportLearnMore": "https://help.dydx.exchange",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -507,7 +583,17 @@
"documentation": "https://docs.dydx.exchange/", "documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"accountExportLearnMore": "https://help.dydx.exchange",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -571,7 +657,17 @@
"documentation": "https://docs.dydx.exchange/", "documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"accountExportLearnMore": "https://help.dydx.exchange",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -635,7 +731,17 @@
"documentation": "https://docs.dydx.exchange/", "documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"accountExportLearnMore": "https://help.dydx.exchange",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -699,7 +805,17 @@
"documentation": "https://docs.dydx.exchange/", "documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"accountExportLearnMore": "https://help.dydx.exchange",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -824,10 +940,20 @@
"privacy": "https://dydx.exchange/privacy", "privacy": "https://dydx.exchange/privacy",
"statusPage": "https://status.v4testnet.dydx.exchange/", "statusPage": "https://status.v4testnet.dydx.exchange/",
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}", "mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
"documentation": "https://v4-teacher.vercel.app/", "documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx", "community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog" "blogs": "https://www.dydx.foundation/blog",
"foundation": "https://www.dydx.foundation",
"help": "https://help.dydx.exchange/",
"initialMarginFractionLearnmore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
"reduceOnlyLearnmore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnmore": "https://help.dydx.exchange",
"stakingLearnmore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"accountExportLearnmore": "https://help.dydx.exchange",
"walletLearnmore": "https://www.dydx.academy/video/defi-wallet"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {
@ -888,11 +1014,20 @@
"tos": "[HTTP link to TOS]", "tos": "[HTTP link to TOS]",
"privacy": "[HTTP link to Privacy Policy]", "privacy": "[HTTP link to Privacy Policy]",
"mintscan": "[HTTP link to Mintscan, with {tx_hash} placeholder]", "mintscan": "[HTTP link to Mintscan, with {tx_hash} placeholder]",
"documentation": "[HTTP link to documentation, can be null]", "mintscanBase": "[HTTP link to TOS mintsacn base url]",
"community": "[HTTP link to community, can be null]",
"feedback": "[HTTP link to feedback form, can be null]", "feedback": "[HTTP link to feedback form, can be null]",
"blogs": "[HTTP link to blogs, can be null]", "blogs": "[HTTP link to blogs, can be null]",
"help": "[HTTP link to help page, can be null]" "foundation": "[HTTP link to foundation, can be null]",
"initialMarginFractionLearnMore": "[HTTP link to initial margin fraction learn more, can be null]",
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"documentation": "[HTTP link to documentation, can be null]",
"community": "[HTTP link to community, can be null]",
"help": "[HTTP link to help page, can be null]",
"governanceLearnMore": "[HTTP link to governance learn more, can be null]",
"stakingLearnMore": "[HTTP link to staking learn more, can be null]",
"keplrDashboard": "[HTTP link to keplr dashboard, can be null]",
"accountExportLearnMore": "[HTTP link to account export learn more, can be null]",
"walletLearnMore": "[HTTP link to wallet learn more, can be null]"
}, },
"wallets": { "wallets": {
"walletconnect": { "walletconnect": {

View File

@ -2,11 +2,13 @@ import type { ReactNode } from 'react';
import styled, { AnyStyledComponent } from 'styled-components'; import styled, { AnyStyledComponent } from 'styled-components';
import { Content, Portal, Provider, Root, Trigger, Arrow } from '@radix-ui/react-tooltip'; import { Content, Portal, Provider, Root, Trigger, Arrow } from '@radix-ui/react-tooltip';
import { STRING_KEYS } from '@/constants/localization';
import { tooltipStrings } from '@/constants/tooltips'; import { tooltipStrings } from '@/constants/tooltips';
import { useStringGetter } from '@/hooks'; import { useStringGetter, useURLConfigs } from '@/hooks';
import { Icon, IconName } from '@/components/Icon'; import { Icon, IconName } from '@/components/Icon';
import { Link } from '@/components/Link';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
import { popoverMixins } from '@/styles/popoverMixins'; import { popoverMixins } from '@/styles/popoverMixins';
@ -38,20 +40,24 @@ export const WithTooltip = ({
slotTooltip, slotTooltip,
}: ElementProps & StyleProps) => { }: ElementProps & StyleProps) => {
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
const urlConfigs = useURLConfigs();
const getTooltipStrings = tooltip && tooltipStrings[tooltip]; const getTooltipStrings = tooltip && tooltipStrings[tooltip];
if (!getTooltipStrings && !tooltipString && !slotTooltip) return <>{children}</>; if (!getTooltipStrings && !tooltipString && !slotTooltip) return <>{children}</>;
let tooltipTitle; let tooltipTitle;
let tooltipBody; let tooltipBody;
let tooltipLearnMore;
if (getTooltipStrings) { if (getTooltipStrings) {
const { title, body } = getTooltipStrings({ const { title, body, learnMoreLink } = getTooltipStrings({
stringGetter, stringGetter,
stringParams, stringParams,
urlConfigs,
}); });
tooltipTitle = title; tooltipTitle = title;
tooltipBody = body; tooltipBody = body;
tooltipLearnMore = learnMoreLink;
} else { } else {
tooltipBody = tooltipString; tooltipBody = tooltipString;
} }
@ -72,6 +78,13 @@ export const WithTooltip = ({
<dl> <dl>
{tooltipTitle && <dt>{tooltipTitle}</dt>} {tooltipTitle && <dt>{tooltipTitle}</dt>}
{tooltipBody && <dd>{tooltipBody}</dd>} {tooltipBody && <dd>{tooltipBody}</dd>}
{tooltipLearnMore && (
<dd>
<Styled.LearnMore href={tooltipLearnMore}>
{stringGetter({ key: STRING_KEYS.LEARN_MORE })}
</Styled.LearnMore>
</dd>
)}
<Styled.Arrow /> <Styled.Arrow />
</dl> </dl>
)} )}
@ -142,3 +155,7 @@ Styled.Arrow = styled(Arrow)`
Styled.Icon = styled(Icon)` Styled.Icon = styled(Icon)`
color: var(--color-text-0); color: var(--color-text-0);
`; `;
Styled.LearnMore = styled(Link)`
--link-color: var(--color-accent);
`;

View File

@ -8,6 +8,8 @@ import {
WARNINGS_STRING_KEYS, WARNINGS_STRING_KEYS,
} from '@dydxprotocol/v4-localization'; } from '@dydxprotocol/v4-localization';
import { type LinksConfigs } from '@/hooks/useURLConfigs';
export { TOOLTIP_STRING_KEYS } from '@dydxprotocol/v4-localization'; export { TOOLTIP_STRING_KEYS } from '@dydxprotocol/v4-localization';
export enum SupportedLocales { export enum SupportedLocales {
@ -79,9 +81,11 @@ export type TooltipStrings = {
[key: string]: ({ [key: string]: ({
stringGetter, stringGetter,
stringParams, stringParams,
urlConfigs,
}: { }: {
stringGetter: StringGetterFunction; stringGetter: StringGetterFunction;
stringParams?: any; stringParams?: any;
urlConfigs?: LinksConfigs;
}) => { }) => {
title: string; title: string;
body: string; body: string;

View File

@ -37,7 +37,3 @@ export const HISTORY_ROUTE = `${AppRoute.Portfolio}/${PortfolioRoute.History}/:s
export const DEFAULT_TRADE_ROUTE = `${AppRoute.Trade}/${DEFAULT_MARKETID}`; export const DEFAULT_TRADE_ROUTE = `${AppRoute.Trade}/${DEFAULT_MARKETID}`;
export const SETTINGS_ROUTE = `${AppRoute.Settings}/*`; export const SETTINGS_ROUTE = `${AppRoute.Settings}/*`;
export const DEFAULT_DOCUMENT_TITLE = 'dYdX'; export const DEFAULT_DOCUMENT_TITLE = 'dYdX';
export enum ExternalLink {
Foundation = 'https://dydx.foundation',
}

View File

@ -57,10 +57,10 @@ export const tradeTooltips: TooltipStrings = {
title: stringGetter({ key: TOOLTIP_STRING_KEYS.INDEX_PRICE_TITLE }), title: stringGetter({ key: TOOLTIP_STRING_KEYS.INDEX_PRICE_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.INDEX_PRICE_BODY }), body: stringGetter({ key: TOOLTIP_STRING_KEYS.INDEX_PRICE_BODY }),
}), }),
'initial-margin-fraction': ({ stringGetter }) => ({ 'initial-margin-fraction': ({ stringGetter, urlConfigs }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.INITIAL_MARGIN_FRACTION_TITLE }), title: stringGetter({ key: TOOLTIP_STRING_KEYS.INITIAL_MARGIN_FRACTION_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.INITIAL_MARGIN_FRACTION_BODY }), body: stringGetter({ key: TOOLTIP_STRING_KEYS.INITIAL_MARGIN_FRACTION_BODY }),
learnMoreLink: 'https://help.dydx.exchange/articles/5232637-maximum-position-sizes', learnMoreLink: urlConfigs?.initialMarginFractionLearnMore,
}), }),
'initial-stop': ({ stringGetter }) => ({ 'initial-stop': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.INITIAL_STOP_TITLE }), title: stringGetter({ key: TOOLTIP_STRING_KEYS.INITIAL_STOP_TITLE }),
@ -146,10 +146,10 @@ export const tradeTooltips: TooltipStrings = {
title: stringGetter({ key: TOOLTIP_STRING_KEYS.REALIZED_PNL_TITLE }), title: stringGetter({ key: TOOLTIP_STRING_KEYS.REALIZED_PNL_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REALIZED_PNL_BODY }), body: stringGetter({ key: TOOLTIP_STRING_KEYS.REALIZED_PNL_BODY }),
}), }),
'reduce-only': ({ stringGetter }) => ({ 'reduce-only': ({ stringGetter, urlConfigs }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_TITLE }), title: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_BODY }), body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_BODY }),
learnMoreLink: 'https://help.dydx.exchange/articles/6345793-reduce-only-orders', learnMoreLink: urlConfigs?.reduceOnlyLearnMore,
}), }),
spread: () => ({ spread: () => ({
title: 'Spread', title: 'Spread',

View File

@ -22,6 +22,7 @@ import { useShouldShowFooter } from './useShouldShowFooter';
import { useSelectedNetwork } from './useSelectedNetwork'; import { useSelectedNetwork } from './useSelectedNetwork';
import { useStringGetter } from './useStringGetter'; import { useStringGetter } from './useStringGetter';
import { useSubaccount } from './useSubaccount'; import { useSubaccount } from './useSubaccount';
import { useURLConfigs } from './useURLConfigs';
export { export {
useApiState, useApiState,
@ -48,4 +49,5 @@ export {
useSelectedNetwork, useSelectedNetwork,
useStringGetter, useStringGetter,
useSubaccount, useSubaccount,
useURLConfigs,
}; };

View File

@ -0,0 +1,50 @@
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { useSelectedNetwork } from '@/hooks';
const FALLBACK_URL = 'https://help.dydx.exchange/';
export interface LinksConfigs {
tos: string,
privacy: string,
mintscan: string,
mintscanBase: string,
feedback?: string,
help?: string,
blogs?: string,
foundation?: string,
initialMarginFractionLearnMore?: string,
reduceOnlyLearnMore?: string,
documentation?: string,
community?: string,
governanceLearnMore?: string,
stakingLearnMore?: string,
keplrDashboard?: string,
accountExportLearnMore?: string,
walletLearnMore?: string
}
export const useURLConfigs = (): LinksConfigs => {
const { selectedNetwork } = useSelectedNetwork();
const linksConfigs = ENVIRONMENT_CONFIG_MAP[selectedNetwork].links as LinksConfigs;
return {
tos: linksConfigs.tos,
privacy: linksConfigs.privacy,
mintscan: linksConfigs.mintscan,
mintscanBase: linksConfigs.mintscanBase,
feedback: linksConfigs.feedback || FALLBACK_URL,
help: linksConfigs.help || FALLBACK_URL,
blogs: linksConfigs.blogs || FALLBACK_URL,
foundation: linksConfigs.foundation || FALLBACK_URL,
initialMarginFractionLearnMore: linksConfigs.initialMarginFractionLearnMore || FALLBACK_URL,
reduceOnlyLearnMore: linksConfigs.reduceOnlyLearnMore || FALLBACK_URL,
documentation: linksConfigs.documentation || FALLBACK_URL,
community: linksConfigs.community || FALLBACK_URL,
governanceLearnMore: linksConfigs.governanceLearnMore || FALLBACK_URL,
stakingLearnMore: linksConfigs.stakingLearnMore || FALLBACK_URL,
keplrDashboard: linksConfigs.keplrDashboard || FALLBACK_URL,
accountExportLearnMore: linksConfigs.accountExportLearnMore || FALLBACK_URL,
walletLearnMore: linksConfigs.walletLearnMore || FALLBACK_URL,
};
};

View File

@ -8,7 +8,7 @@ import { STRING_KEYS } from '@/constants/localization';
import { AppRoute } from '@/constants/routes'; import { AppRoute } from '@/constants/routes';
import { LogoShortIcon, BellStrokeIcon } from '@/icons'; import { LogoShortIcon, BellStrokeIcon } from '@/icons';
import { useTokenConfigs, useStringGetter } from '@/hooks'; import { useTokenConfigs, useStringGetter, useURLConfigs } from '@/hooks';
import { Icon, IconName } from '@/components/Icon'; import { Icon, IconName } from '@/components/Icon';
import { IconButton } from '@/components/IconButton'; import { IconButton } from '@/components/IconButton';
@ -28,6 +28,7 @@ import breakpoints from '@/styles/breakpoints';
export const HeaderDesktop = () => { export const HeaderDesktop = () => {
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
const { documentation, community, mintscanBase } = useURLConfigs();
const dispatch = useDispatch(); const dispatch = useDispatch();
const { chainTokenLabel } = useTokenConfigs(); const { chainTokenLabel } = useTokenConfigs();
@ -63,19 +64,19 @@ export const HeaderDesktop = () => {
value: 'DOCUMENTATION', value: 'DOCUMENTATION',
slotBefore: <Icon iconName={IconName.Terminal} />, slotBefore: <Icon iconName={IconName.Terminal} />,
label: stringGetter({ key: STRING_KEYS.DOCUMENTATION }), label: stringGetter({ key: STRING_KEYS.DOCUMENTATION }),
href: 'https://docs.dydx.exchange/', href: documentation,
}, },
{ {
value: 'MINTSCAN', value: 'MINTSCAN',
slotBefore: <Icon iconName={IconName.Mintscan} />, slotBefore: <Icon iconName={IconName.Mintscan} />,
label: stringGetter({ key: STRING_KEYS.MINTSCAN }), label: stringGetter({ key: STRING_KEYS.MINTSCAN }),
href: 'https://testnet.mintscan.io/dydx-testnet', href: mintscanBase,
}, },
{ {
value: 'COMMUNITY', value: 'COMMUNITY',
slotBefore: <Icon iconName={IconName.Discord} />, slotBefore: <Icon iconName={IconName.Discord} />,
label: stringGetter({ key: STRING_KEYS.COMMUNITY }), label: stringGetter({ key: STRING_KEYS.COMMUNITY }),
href: 'https://discord.gg/dydx', href: community,
}, },
{ {
value: 'TERMS_OF_USE', value: 'TERMS_OF_USE',

View File

@ -5,7 +5,7 @@ import { STRING_KEYS } from '@/constants/localization';
import { ButtonAction, ButtonSize } from '@/constants/buttons'; import { ButtonAction, ButtonSize } from '@/constants/buttons';
import { DialogTypes } from '@/constants/dialogs'; import { DialogTypes } from '@/constants/dialogs';
import { useBreakpoints, useStringGetter } from '@/hooks'; import { useBreakpoints, useStringGetter, useURLConfigs } from '@/hooks';
import { breakpoints } from '@/styles'; import { breakpoints } from '@/styles';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
@ -20,15 +20,10 @@ import { openDialog } from '@/state/dialogs';
import { DYDXBalancePanel } from './DYDXBalancePanel'; import { DYDXBalancePanel } from './DYDXBalancePanel';
import { MigratePanel } from './MigratePanel'; import { MigratePanel } from './MigratePanel';
// TODO: consolidate help link urls to env variables
const GOVERNANCE_HELP_URL = 'https://help.dydx.exchange/';
const STAKING_HELP_URL =
'https://docs.dydx.community/dydx-chain-documentation/staking/how-to-stake';
export const RewardsPage = () => { export const RewardsPage = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
const { governanceLearnMore, stakingLearnMore } = useURLConfigs();
const { isTablet, isNotTablet } = useBreakpoints(); const { isTablet, isNotTablet } = useBreakpoints();
const panelArrow = ( const panelArrow = (
@ -58,7 +53,7 @@ export const RewardsPage = () => {
> >
<Styled.Description> <Styled.Description>
{stringGetter({ key: STRING_KEYS.GOVERNANCE_DESCRIPTION })} {stringGetter({ key: STRING_KEYS.GOVERNANCE_DESCRIPTION })}
<Link href={GOVERNANCE_HELP_URL} onClick={(e) => e.stopPropagation()}> <Link href={governanceLearnMore} onClick={(e) => e.stopPropagation()}>
{stringGetter({ key: STRING_KEYS.LEARN_MORE })} {stringGetter({ key: STRING_KEYS.LEARN_MORE })}
</Link> </Link>
</Styled.Description> </Styled.Description>
@ -71,7 +66,7 @@ export const RewardsPage = () => {
> >
<Styled.Description> <Styled.Description>
{stringGetter({ key: STRING_KEYS.STAKING_DESCRIPTION })} {stringGetter({ key: STRING_KEYS.STAKING_DESCRIPTION })}
<Link href={STAKING_HELP_URL} onClick={(e) => e.stopPropagation()}> <Link href={stakingLearnMore} onClick={(e) => e.stopPropagation()}>
{stringGetter({ key: STRING_KEYS.LEARN_MORE })} {stringGetter({ key: STRING_KEYS.LEARN_MORE })}
</Link> </Link>
</Styled.Description> </Styled.Description>

View File

@ -2,7 +2,7 @@ import styled, { type AnyStyledComponent } from 'styled-components';
import { ButtonAction, ButtonSize, ButtonType } from '@/constants/buttons'; import { ButtonAction, ButtonSize, ButtonType } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization'; import { STRING_KEYS } from '@/constants/localization';
import { useBreakpoints, useStringGetter } from '@/hooks'; import { useBreakpoints, useStringGetter, useURLConfigs } from '@/hooks';
import { Button } from '@/components/Button'; import { Button } from '@/components/Button';
import { Dialog, DialogPlacement } from '@/components/Dialog'; import { Dialog, DialogPlacement } from '@/components/Dialog';
@ -15,12 +15,10 @@ type ElementProps = {
setIsOpen: (open: boolean) => void; setIsOpen: (open: boolean) => void;
}; };
// TODO: replace placeholder URL with real URLs when avaialble
const KEPLR_DASHBOARD_URL = 'https://testnet.keplr.app/';
const HELP_URL = 'https://help.dydx.exchange/en/articles/2921366-how-do-i-create-an-account-or-sign-up';
export const ExternalNavKeplrDialog = ({ setIsOpen }: ElementProps) => { export const ExternalNavKeplrDialog = ({ setIsOpen }: ElementProps) => {
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
const { keplrDashboard, accountExportLearnMore } = useURLConfigs();
const { isTablet } = useBreakpoints(); const { isTablet } = useBreakpoints();
return ( return (
@ -31,7 +29,7 @@ export const ExternalNavKeplrDialog = ({ setIsOpen }: ElementProps) => {
placement={isTablet ? DialogPlacement.FullScreen : DialogPlacement.Default} placement={isTablet ? DialogPlacement.FullScreen : DialogPlacement.Default}
> >
<Styled.Content> <Styled.Content>
<Styled.Button type={ButtonType.Link} size={ButtonSize.XLarge} href={KEPLR_DASHBOARD_URL}> <Styled.Button type={ButtonType.Link} size={ButtonSize.XLarge} href={keplrDashboard}>
<span> <span>
{stringGetter({ {stringGetter({
key: STRING_KEYS.NAVIGATE_TO_KEPLR, key: STRING_KEYS.NAVIGATE_TO_KEPLR,
@ -48,7 +46,7 @@ export const ExternalNavKeplrDialog = ({ setIsOpen }: ElementProps) => {
/> />
</Styled.Button> </Styled.Button>
<Styled.Button type={ButtonType.Link} size={ButtonSize.XLarge} href={HELP_URL}> <Styled.Button type={ButtonType.Link} size={ButtonSize.XLarge} href={accountExportLearnMore}>
<span> <span>
{stringGetter({ {stringGetter({
key: STRING_KEYS.LEARN_TO_EXPORT, key: STRING_KEYS.LEARN_TO_EXPORT,

View File

@ -2,10 +2,10 @@ import { useMemo } from 'react';
import styled, { AnyStyledComponent } from 'styled-components'; import styled, { AnyStyledComponent } from 'styled-components';
import { STRING_KEYS } from '@/constants/localization'; import { STRING_KEYS } from '@/constants/localization';
import { useStringGetter } from '@/hooks'; import { useStringGetter, useURLConfigs } from '@/hooks';
import { ChatIcon, FeedbackIcon, FileIcon, TerminalIcon } from '@/icons';
import { ComboboxDialogMenu } from '@/components/ComboboxDialogMenu'; import { ComboboxDialogMenu } from '@/components/ComboboxDialogMenu';
import { Icon, IconName } from '@/components/Icon';
import { isTruthy } from '@/lib/isTruthy'; import { isTruthy } from '@/lib/isTruthy';
@ -13,39 +13,24 @@ type ElementProps = {
setIsOpen: (open: boolean) => void; setIsOpen: (open: boolean) => void;
}; };
const HELP_LINKS = {
apiDocumentation: 'https://v4-teacher.vercel.app/',
helpCenter: null,
feedback: null,
};
export const HelpDialog = ({ setIsOpen }: ElementProps) => { export const HelpDialog = ({ setIsOpen }: ElementProps) => {
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
const { help: helpCenter, community } = useURLConfigs();
const HELP_ITEMS = useMemo( const HELP_ITEMS = useMemo(
() => [ () => [
{ {
group: 'help-items', group: 'help-items',
items: [ items: [
HELP_LINKS.helpCenter && { helpCenter && {
value: 'help-center', value: 'help-center',
label: stringGetter({ key: STRING_KEYS.HELP_CENTER }), label: stringGetter({ key: STRING_KEYS.HELP_CENTER }),
description: stringGetter({ key: STRING_KEYS.HELP_CENTER_DESCRIPTION }), description: stringGetter({ key: STRING_KEYS.HELP_CENTER_DESCRIPTION }),
onSelect: () => { onSelect: () => {
HELP_LINKS.helpCenter && globalThis.open(HELP_LINKS.helpCenter, '_blank'); helpCenter && globalThis.open(helpCenter, '_blank');
setIsOpen(false); setIsOpen(false);
}, },
slotBefore: <FileIcon />, slotBefore: <Icon iconName={IconName.File} />,
},
HELP_LINKS.apiDocumentation && {
value: 'api-documentation',
label: stringGetter({ key: STRING_KEYS.API_DOCUMENTATION }),
description: stringGetter({ key: STRING_KEYS.API_DOCUMENTATION_DESCRIPTION }),
onSelect: () => {
HELP_LINKS.apiDocumentation && globalThis.open(HELP_LINKS.apiDocumentation, '_blank');
setIsOpen(false);
},
slotBefore: <TerminalIcon />,
}, },
globalThis?.Intercom && { globalThis?.Intercom && {
value: 'live-chat', value: 'live-chat',
@ -55,22 +40,22 @@ export const HelpDialog = ({ setIsOpen }: ElementProps) => {
globalThis.Intercom('show'); globalThis.Intercom('show');
setIsOpen(false); setIsOpen(false);
}, },
slotBefore: <ChatIcon />, slotBefore: <Icon iconName={IconName.Chat} />,
}, },
HELP_LINKS.feedback && { community && {
value: 'feedback', value: 'community',
label: stringGetter({ key: STRING_KEYS.PROVIDE_FEEDBACK }), label: stringGetter({ key: STRING_KEYS.COMMUNITY }),
description: stringGetter({ key: STRING_KEYS.PROVIDE_FEEDBACK_DESCRIPTION }), description: stringGetter({ key: STRING_KEYS.COMMUNITY_DESCRIPTION }),
onSelect: () => { onSelect: () => {
HELP_LINKS.feedback && globalThis.open(HELP_LINKS.feedback, '_blank'); community && globalThis.open(community, '_blank');
setIsOpen(false); setIsOpen(false);
}, },
slotBefore: <FeedbackIcon />, slotBefore: <Icon iconName={IconName.Discord} />,
}, },
].filter(isTruthy), ].filter(isTruthy),
}, },
], ],
[stringGetter] [stringGetter, helpCenter, community]
); );
return ( return (

View File

@ -13,16 +13,15 @@ import { Button } from '@/components/Button';
import { Icon } from '@/components/Icon'; import { Icon } from '@/components/Icon';
import { Link } from '@/components/Link'; import { Link } from '@/components/Link';
import { useAccounts, useStringGetter } from '@/hooks'; import { useAccounts, useStringGetter, useURLConfigs } from '@/hooks';
import { useDisplayedWallets } from '@/hooks/useDisplayedWallets'; import { useDisplayedWallets } from '@/hooks/useDisplayedWallets';
import { breakpoints } from '@/styles'; import { breakpoints } from '@/styles';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
const aboutWalletsLink = `https://www.dydx.academy/video/defi-wallet`;
export const ChooseWallet = () => { export const ChooseWallet = () => {
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
const { walletLearnMore } = useURLConfigs();
const displayedWallets = useDisplayedWallets(); const displayedWallets = useDisplayedWallets();
@ -63,7 +62,7 @@ export const ChooseWallet = () => {
</Styled.Wallets> </Styled.Wallets>
<Styled.Footer> <Styled.Footer>
<Link href={aboutWalletsLink} withIcon> <Link href={walletLearnMore} withIcon>
{stringGetter({ key: STRING_KEYS.ABOUT_WALLETS })} {stringGetter({ key: STRING_KEYS.ABOUT_WALLETS })}
</Link> </Link>
</Styled.Footer> </Styled.Footer>

View File

@ -15,6 +15,7 @@ import {
useTokenConfigs, useTokenConfigs,
useStringGetter, useStringGetter,
useAccountBalance, useAccountBalance,
useURLConfigs,
} from '@/hooks'; } from '@/hooks';
import { OnboardingTriggerButton } from '@/views/dialogs/OnboardingTriggerButton'; import { OnboardingTriggerButton } from '@/views/dialogs/OnboardingTriggerButton';
@ -36,10 +37,9 @@ import { truncateAddress } from '@/lib/wallet';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
import { headerMixins } from '@/styles/headerMixins'; import { headerMixins } from '@/styles/headerMixins';
const explorerBaseUri = 'https://testnet.mintscan.io/dydx-testnet';
export const AccountMenu = () => { export const AccountMenu = () => {
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
const { mintscanBase } = useURLConfigs();
const { isTablet } = useBreakpoints(); const { isTablet } = useBreakpoints();
const dispatch = useDispatch(); const dispatch = useDispatch();
const onboardingState = useSelector(getOnboardingState); const onboardingState = useSelector(getOnboardingState);
@ -92,7 +92,7 @@ export const AccountMenu = () => {
/> />
<IconButton <IconButton
action={ButtonAction.Base} action={ButtonAction.Base}
href={`${explorerBaseUri}/account/${dydxAddress}`} href={`${mintscanBase}/account/${dydxAddress}`}
iconName={IconName.LinkOut} iconName={IconName.LinkOut}
shape={ButtonShape.Square} shape={ButtonShape.Square}
type={ButtonType.Link} type={ButtonType.Link}
@ -167,7 +167,7 @@ export const AccountMenu = () => {
// value: 'ViewInExplorer', // value: 'ViewInExplorer',
// icon: <Icon iconName={IconName.Etherscan} />, // icon: <Icon iconName={IconName.Etherscan} />,
// label: stringGetter({ key: STRING_KEYS.OPEN_IN_ETHERSCAN }), // label: stringGetter({ key: STRING_KEYS.OPEN_IN_ETHERSCAN }),
// onSelect: () => globalThis.open(`${explorerBaseUri}/address/${address}`), // onSelect: () => globalThis.open(`${mintscanBase}/address/${address}`),
// separator: true, // separator: true,
// }, // },
...(onboardingState === OnboardingState.AccountConnected && hdKey ...(onboardingState === OnboardingState.AccountConnected && hdKey