From 0d4c5a547ab233ec5cd79997c45dde506a6fd917 Mon Sep 17 00:00:00 2001 From: Bill Date: Fri, 27 Oct 2023 11:41:00 -0700 Subject: [PATCH 1/6] Abort key derivation if second signature fails (#109) --- package.json | 2 +- pnpm-lock.yaml | 8 ++++---- src/views/dialogs/OnboardingDialog/GenerateKeys.tsx | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 67aff90..6037140 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@cosmjs/proto-signing": "^0.31.0", "@cosmjs/stargate": "^0.31.0", "@cosmjs/tendermint-rpc": "^0.31.0", - "@dydxprotocol/v4-abacus": "^0.7.6", + "@dydxprotocol/v4-abacus": "^1.0.3", "@dydxprotocol/v4-client-js": "^0.40.3", "@dydxprotocol/v4-localization": "^0.1.32", "@ethersproject/providers": "^5.7.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f5924fc..65dbd3a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,8 +27,8 @@ dependencies: specifier: ^0.31.0 version: 0.31.0 '@dydxprotocol/v4-abacus': - specifier: ^0.7.6 - version: 0.7.6 + specifier: ^1.0.3 + version: 1.0.3 '@dydxprotocol/v4-client-js': specifier: ^0.40.3 version: 0.40.3 @@ -979,8 +979,8 @@ packages: resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==} dev: true - /@dydxprotocol/v4-abacus@0.7.6: - resolution: {integrity: sha512-FdDXRaFMfxhyrJJs0dNrb1KG6X95lPHelua1yCn/SVgzwGaAqlJczrzmdh98INntuRAgIxOu69R5mCGyekumyg==} + /@dydxprotocol/v4-abacus@1.0.3: + resolution: {integrity: sha512-GuX37/DMMNSke8ZFcw52II7IVJfUgVGHqoi1Uw2cUb+hgIjjSG3OtbyRWedm5r6nqWq8BNLOexI0VVFB6OMVYg==} dev: false /@dydxprotocol/v4-client-js@0.40.3: diff --git a/src/views/dialogs/OnboardingDialog/GenerateKeys.tsx b/src/views/dialogs/OnboardingDialog/GenerateKeys.tsx index 5ed9328..092e253 100644 --- a/src/views/dialogs/OnboardingDialog/GenerateKeys.tsx +++ b/src/views/dialogs/OnboardingDialog/GenerateKeys.tsx @@ -130,12 +130,14 @@ export const GenerateKeys = ({ } } } catch (error) { + setStatus(EvmDerivedAccountStatus.NotDerived); const { message } = parseWalletError({ error, stringGetter }); if (message) { track(AnalyticsEvent.OnboardingWalletIsNonDeterministic); setError(message); } + return; } await setWalletFromEvmSignature(signature); From b479531e3414c39fdb1f49b418b465e2280fd9f0 Mon Sep 17 00:00:00 2001 From: aleka Date: Fri, 27 Oct 2023 16:13:48 -0400 Subject: [PATCH 2/6] update v4 docs link (#102) --- public/configs/env.json | 16 ++++++++-------- src/layout/Header/HeaderDesktop.tsx | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/public/configs/env.json b/public/configs/env.json index 61488b2..a27bf70 100644 --- a/public/configs/env.json +++ b/public/configs/env.json @@ -308,7 +308,7 @@ "tos": "https://dydx.exchange/v4-terms", "privacy": "https://dydx.exchange/privacy", "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", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "blogs": "https://www.dydx.foundation/blog", @@ -372,7 +372,7 @@ "tos": "https://dydx.exchange/v4-terms", "privacy": "https://dydx.exchange/privacy", "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", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "blogs": "https://www.dydx.foundation/blog", @@ -439,7 +439,7 @@ "tos": "https://dydx.exchange/v4-terms", "privacy": "https://dydx.exchange/privacy", "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", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "blogs": "https://www.dydx.foundation/blog" @@ -503,7 +503,7 @@ "privacy": "https://dydx.exchange/privacy", "statusPage": "https://status.v4testnet.dydx.exchange/", "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", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "blogs": "https://www.dydx.foundation/blog" @@ -567,7 +567,7 @@ "privacy": "https://dydx.exchange/privacy", "statusPage": "https://status.v4testnet.dydx.exchange/", "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", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "blogs": "https://www.dydx.foundation/blog" @@ -631,7 +631,7 @@ "privacy": "https://dydx.exchange/privacy", "statusPage": "https://status.v4testnet.dydx.exchange/", "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", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "blogs": "https://www.dydx.foundation/blog" @@ -695,7 +695,7 @@ "privacy": "https://dydx.exchange/privacy", "statusPage": "https://status.v4testnet.dydx.exchange/", "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", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "blogs": "https://www.dydx.foundation/blog" @@ -759,7 +759,7 @@ "privacy": "https://dydx.exchange/privacy", "statusPage": "https://status.v4testnet.dydx.exchange/", "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", "feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform", "blogs": "https://www.dydx.foundation/blog" diff --git a/src/layout/Header/HeaderDesktop.tsx b/src/layout/Header/HeaderDesktop.tsx index de92dfd..464c6c7 100644 --- a/src/layout/Header/HeaderDesktop.tsx +++ b/src/layout/Header/HeaderDesktop.tsx @@ -62,7 +62,7 @@ export const HeaderDesktop = () => { value: 'DOCUMENTATION', slotBefore: , label: stringGetter({ key: STRING_KEYS.DOCUMENTATION }), - href: 'https://v4-teacher.vercel.app/', + href: 'https://docs.dydx.exchange/', }, { value: 'MINTSCAN', From e7da21962a970c84a4b78a32e95112d2d18cffe5 Mon Sep 17 00:00:00 2001 From: aleka Date: Fri, 27 Oct 2023 16:14:34 -0400 Subject: [PATCH 3/6] add entry point to token migration (#98) * update migrate panel * address feedback --- .env.example | 3 +- src/components/Icon.tsx | 3 + src/components/Panel.tsx | 57 ++-- src/icons/index.ts | 1 + src/icons/migrate.svg | 9 + src/lib/wagmi.ts | 24 +- src/pages/Profile.tsx | 24 +- src/pages/rewards/MigratePanel.tsx | 222 +++++++++++++++ src/pages/rewards/RewardsPage.tsx | 279 +++---------------- src/views/dialogs/ExternalNavKeplrDialog.tsx | 1 + 10 files changed, 345 insertions(+), 278 deletions(-) create mode 100644 src/icons/migrate.svg create mode 100644 src/pages/rewards/MigratePanel.tsx diff --git a/.env.example b/.env.example index 3a0d1b2..b7a842e 100644 --- a/.env.example +++ b/.env.example @@ -6,4 +6,5 @@ VITE_PK_ENCRYPTION_KEY= VITE_WALLETCONNECT2_PROJECT_ID= -VITE_V3_TOKEN_ADDRESS= \ No newline at end of file +VITE_V3_TOKEN_ADDRESS= +VITE_TOKEN_MIGRATION_URI= \ No newline at end of file diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index b7bf634..5e8c7cf 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -40,6 +40,7 @@ import { LockIcon, LogoShortIcon, MenuIcon, + MigrateIcon, MintscanIcon, OrderbookIcon, OrderCanceledIcon, @@ -108,6 +109,7 @@ export enum IconName { Lock = 'Lock', LogoShort = 'LogoShort', Menu = 'Menu', + Migrate = 'Migrate', Mintscan = 'Mintscan', Onboarding = 'Onboarding', Orderbook = 'OrderbookIcon', @@ -177,6 +179,7 @@ const icons = { [IconName.Lock]: LockIcon, [IconName.LogoShort]: LogoShortIcon, [IconName.Menu]: MenuIcon, + [IconName.Migrate]: MigrateIcon, [IconName.Mintscan]: MintscanIcon, [IconName.Orderbook]: OrderbookIcon, [IconName.OrderCanceled]: OrderCanceledIcon, diff --git a/src/components/Panel.tsx b/src/components/Panel.tsx index cd33955..dec52ea 100644 --- a/src/components/Panel.tsx +++ b/src/components/Panel.tsx @@ -8,6 +8,7 @@ import { layoutMixins } from '@/styles/layoutMixins'; type PanelProps = { slotHeaderContent?: string; slotHeader?: React.ReactNode; + slotRight?: React.ReactNode; children?: React.ReactNode; href?: string; onHeaderClick?: () => void; @@ -22,6 +23,7 @@ type PanelStyleProps = { export const Panel = ({ slotHeaderContent, slotHeader, + slotRight, children, href, onHeaderClick, @@ -30,55 +32,61 @@ export const Panel = ({ className, }: PanelProps & PanelStyleProps) => ( - {href ? ( - - {slotHeader ? ( - slotHeader - ) : ( + + {href ? ( + + {slotHeader ? ( + slotHeader + ) : ( + + {slotHeaderContent} + + + )} + + ) : slotHeader ? ( + slotHeader + ) : ( + slotHeaderContent && ( {slotHeaderContent} - - )} - - ) : slotHeader ? ( - slotHeader - ) : ( - slotHeaderContent && ( - - {slotHeaderContent} - - ) - )} - {children} + ) + )} + {children} + + {slotRight} ); const Styled: Record = {}; Styled.Panel = styled.section` - ${layoutMixins.flexColumn} + ${layoutMixins.row} background-color: var(--color-layer-3); border-radius: 0.875rem; `; +Styled.Left = styled.div` + ${layoutMixins.flexColumn} + width: 100%; +`; + Styled.Header = styled.header<{ hasSeparator?: boolean }>` ${layoutMixins.spacedRow} - - padding: 0.875rem 1rem 0.625rem; - font-size: 0.875rem; + padding: 1rem 1rem; ${({ hasSeparator }) => hasSeparator && css` + padding-bottom: 0.625rem; box-shadow: 0 var(--border-width) var(--border-color); `} `; Styled.Icon = styled(Icon)` color: var(--color-text-0); - font-size: 0.625rem; `; @@ -86,6 +94,5 @@ Styled.Content = styled.div` ${layoutMixins.scrollArea} ${layoutMixins.stickyArea0} --stickyArea0-background: transparent; - - padding: 0.5rem 1rem; + padding: 1rem 1rem; `; diff --git a/src/icons/index.ts b/src/icons/index.ts index f840de8..a1c0667 100644 --- a/src/icons/index.ts +++ b/src/icons/index.ts @@ -35,6 +35,7 @@ export { default as LockIcon } from './lock.svg'; export { default as LogoShortIcon } from './logo-short'; export { default as MarketsIcon } from './markets.svg'; export { default as MenuIcon } from './menu.svg'; +export { default as MigrateIcon } from './migrate.svg'; export { default as MintscanIcon } from './logos/mintscan.svg'; export { default as OrderbookIcon } from './orderbook.svg'; export { default as OverviewIcon } from './overview.svg'; diff --git a/src/icons/migrate.svg b/src/icons/migrate.svg new file mode 100644 index 0000000..c77b877 --- /dev/null +++ b/src/icons/migrate.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/lib/wagmi.ts b/src/lib/wagmi.ts index 469a41f..3a0216a 100644 --- a/src/lib/wagmi.ts +++ b/src/lib/wagmi.ts @@ -46,6 +46,8 @@ import { WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS, } from '@/constants/wallets'; +import { isTruthy } from './isTruthy'; + // Config export const WAGMI_SUPPORTED_CHAINS: Chain[] = [ @@ -78,13 +80,17 @@ export const WAGMI_SUPPORTED_CHAINS: Chain[] = [ celoAlfajores, ]; -const { chains, publicClient, webSocketPublicClient } = configureChains(WAGMI_SUPPORTED_CHAINS, [ - // alchemyProvider({ apiKey: import.meta.env.VITE_ALCHEMY_API_KEY }), - jsonRpcProvider({ - rpc: (chain) => ({ http: chain.rpcUrls.default.http[0] }), - }), - publicProvider(), -]); +const { chains, publicClient, webSocketPublicClient } = configureChains( + WAGMI_SUPPORTED_CHAINS, + [ + import.meta.env.VITE_ALCHEMY_API_KEY && + alchemyProvider({ apiKey: import.meta.env.VITE_ALCHEMY_API_KEY }), + jsonRpcProvider({ + rpc: (chain) => ({ http: chain.rpcUrls.default.http[0] }), + }), + publicProvider(), + ].filter(isTruthy) +); const injectedConnectorOptions = { chains, @@ -202,5 +208,7 @@ export const resolveWagmiConnector = ({ ? createInjectedConnectorWithProvider(walletConnection.provider) : walletConnection.type === WalletConnectionType.WalletConnect2 && walletConfig.walletconnect2Id ? createWalletConnect2ConnectorWithId(walletConfig.walletconnect2Id, walletConnectConfig) - : getConnectors(walletConnectConfig).find(({ id }: { id: string }) => id === walletConnectionConfig.wagmiConnectorId); + : getConnectors(walletConnectConfig).find( + ({ id }: { id: string }) => id === walletConnectionConfig.wagmiConnectorId + ); }; diff --git a/src/pages/Profile.tsx b/src/pages/Profile.tsx index b671e12..03f1908 100644 --- a/src/pages/Profile.tsx +++ b/src/pages/Profile.tsx @@ -17,7 +17,7 @@ import { DialogTypes } from '@/constants/dialogs'; import { STRING_KEYS } from '@/constants/localization'; import { AppRoute, PortfolioRoute, HistoryRoute } from '@/constants/routes'; import { wallets, WalletType } from '@/constants/wallets'; -import { useAccounts, useStringGetter } from '@/hooks'; +import { useAccounts, useStringGetter, useTokenConfigs } from '@/hooks'; import { getOnboardingState } from '@/state/accountSelectors'; import { openDialog } from '@/state/dialogs'; @@ -37,6 +37,7 @@ const Profile = () => { const isConnected = onboardingState !== OnboardingState.Disconnected; const { evmAddress, dydxAddress, walletType } = useAccounts(); + const { chainTokenLabel } = useTokenConfigs(); const { data: ensName } = useEnsName({ address: evmAddress, @@ -137,7 +138,11 @@ const Profile = () => { layout="grid" /> - + { { + const { isNotTablet } = useBreakpoints(); + const stringGetter = useStringGetter(); + + const selectedNetwork = useSelector(getSelectedNetwork); + + const chainId = Number(ENVIRONMENT_CONFIG_MAP[selectedNetwork].ethereumChainId); + + // v3 token is only on mainnet + const { balance: tokenBalance } = useAccountBalance({ + addressOrDenom: chainId === 1 ? import.meta.env.VITE_V3_TOKEN_ADDRESS : undefined, + chainId: 1, + isCosmosChain: false, + }); + + return isNotTablet ? ( + {stringGetter({ key: STRING_KEYS.MIGRATE })}} + slotRight={ + +
+
{stringGetter({ key: STRING_KEYS.AVAILABLE_TO_MIGRATE })}
+ +
+ {import.meta.env.VITE_TOKEN_MIGRATION_URI && ( + + )} +
+ } + > + + {stringGetter({ key: STRING_KEYS.MIGRATE_DESCRIPTION })} + + {stringGetter({ key: STRING_KEYS.LEARN_MORE })} → + + +
+ ) : ( + +

+ + {stringGetter({ key: STRING_KEYS.MIGRATE })} +

+ + + {stringGetter({ + key: STRING_KEYS.FROM_TO, + params: { FROM: Ethereum, TO: dYdX Chain }, + })} + + + } + > + + {stringGetter({ key: STRING_KEYS.AVAILABLE_TO_MIGRATE })} + DYDX + + ), + value: , + }, + ]} + /> + } + > + {import.meta.env.VITE_TOKEN_MIGRATION_URI && ( + + )} + + + {stringGetter({ key: STRING_KEYS.WANT_TO_LEARN })} + + {stringGetter({ key: STRING_KEYS.CLICK_HERE })} + + +
+ ); +}; + +const Styled: Record = {}; + +Styled.MigratePanel = styled(Panel)` + padding: 1rem 1.5rem; +`; + +Styled.Title = styled.h3` + font: var(--font-medium-book); + color: var(--color-text-2); + + padding: 1rem 1.5rem 0; +`; + +Styled.MigrateAction = styled.div` + ${layoutMixins.flexEqualColumns} + align-items: center; + margin-right: 1rem; + gap: 1rem; + padding: 1rem; + width: 100%; + + background-color: var(--color-layer-2); + border: solid var(--border-width) var(--color-border); + border-radius: 0.75rem; +`; + +Styled.Token = styled(Output)` + font: var(--font-large-book); + color: var(--color-text-2); +`; + +Styled.Description = styled.div` + color: var(--color-text-0); + --link-color: var(--color-text-1); +`; + +Styled.MobileMigratePanel = styled(Panel)` + ${layoutMixins.flexColumn} + gap: 1rem; + + align-items: center; +`; + +Styled.MobileMigrateHeader = styled.div` + ${layoutMixins.inlineRow} + gap: 1ch; + + font: var(--font-small-book); + color: var(--color-text-0); + + padding: 1rem 1.5rem 0; + + h3 { + ${layoutMixins.inlineRow} + font: var(--font-large-book); + color: var(--color-text-2); + + svg { + font-size: 1.75rem; + } + } + + span { + margin-top: 0.2rem; + + b { + font-weight: var(--fontWeight-book); + color: var(--color-text-1); + } + } +`; + +Styled.VerticalSeparator = styled(VerticalSeparator)` + z-index: 1; + + && { + height: 1.5rem; + } +`; + +Styled.Details = styled(Details)` + padding: 0.5rem 1rem; +`; + +Styled.WithReceipt = styled(WithReceipt)` + width: 100%; +`; + +Styled.InlineRow = styled.div` + ${layoutMixins.inlineRow} + color: var(--color-text-0); + --link-color: var(--color-text-1); +`; diff --git a/src/pages/rewards/RewardsPage.tsx b/src/pages/rewards/RewardsPage.tsx index ff8b0cd..86affbd 100644 --- a/src/pages/rewards/RewardsPage.tsx +++ b/src/pages/rewards/RewardsPage.tsx @@ -1,134 +1,49 @@ import styled, { AnyStyledComponent } from 'styled-components'; -import { useDispatch, useSelector } from 'react-redux'; +import { useDispatch } from 'react-redux'; -import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks'; import { STRING_KEYS } from '@/constants/localization'; -import { ButtonAction, ButtonSize, ButtonState, ButtonType } from '@/constants/buttons'; +import { ButtonAction, ButtonSize } from '@/constants/buttons'; import { DialogTypes } from '@/constants/dialogs'; -import { useAccountBalance, useBreakpoints, useStringGetter } from '@/hooks'; +import { useBreakpoints, useStringGetter } from '@/hooks'; import { breakpoints } from '@/styles'; import { layoutMixins } from '@/styles/layoutMixins'; -import { Details } from '@/components/Details'; import { Panel } from '@/components/Panel'; import { IconName } from '@/components/Icon'; -import { Button } from '@/components/Button'; import { IconButton } from '@/components/IconButton'; import { Link } from '@/components/Link'; -import { Output, OutputType } from '@/components/Output'; -import { VerticalSeparator } from '@/components/Separator'; -import { WithReceipt } from '@/components/WithReceipt'; import { openDialog } from '@/state/dialogs'; -import { getSelectedNetwork } from '@/state/appSelectors'; import { DYDXBalancePanel } from './DYDXBalancePanel'; +import { MigratePanel } from './MigratePanel'; -// TODO: replace placeholder URL with real URLs when avaialble +// TODO: consolidate help link urls to env variables const GOVERNANCE_HELP_URL = 'https://help.dydx.exchange/'; -const STAKING_HELP_URL = 'https://help.dydx.exchange/'; +const STAKING_HELP_URL = + 'https://docs.dydx.community/dydx-chain-documentation/staking/how-to-stake'; export const RewardsPage = () => { const dispatch = useDispatch(); const stringGetter = useStringGetter(); + const { isTablet, isNotTablet } = useBreakpoints(); - const selectedNetwork = useSelector(getSelectedNetwork); - - // const chainId = Number(ENVIRONMENT_CONFIG_MAP[selectedNetwork].ethereumChainId); - - // const { balance } = useAccountBalance({ - // addressOrDenom: import.meta.env.VITE_V3_TOKEN_ADDRESS, - // assetSymbol: 'DYDX', - // chainId, - // isCosmosChain: false, - // }); - - // const tokenBalance = import.meta.env.VITE_V3_TOKEN_ADDRESS ? balance : 0; + const panelArrow = ( + + + + ); return ( - {/* {isNotTablet ? ( - - -
- - {stringGetter({ key: STRING_KEYS.MIGRATE })} - - - {stringGetter({ key: STRING_KEYS.MIGRATE_DESCRIPTION })} - - {stringGetter({ key: STRING_KEYS.LEARN_MORE })} → - - -
- -
-
{stringGetter({ key: STRING_KEYS.AVAILABLE_TO_MIGRATE })}
-
- -
-
- -
-
-
- ) : ( - -

{stringGetter({ key: STRING_KEYS.MIGRATE })}

- - - {stringGetter({ - key: STRING_KEYS.FROM_TO, - params: { FROM: Ethereum, TO: dYdX Chain }, - })} - - - } - > - , - }, - ]} - /> - } - > - - - - {stringGetter({ key: STRING_KEYS.WANT_TO_LEARN })} - {stringGetter({ key: STRING_KEYS.CLICK_HERE })} - -
- )} */} - + {import.meta.env.VITE_V3_TOKEN_ADDRESS && } {isTablet && ( @@ -138,42 +53,28 @@ export const RewardsPage = () => { {stringGetter({ key: STRING_KEYS.GOVERNANCE })}} + slotRight={panelArrow} onClick={() => dispatch(openDialog({ type: DialogTypes.ExternalNavKeplr }))} > - - - {stringGetter({ key: STRING_KEYS.GOVERNANCE_DESCRIPTION })} - e.stopPropagation()}> - {stringGetter({ key: STRING_KEYS.LEARN_MORE })} → - - - {/* TODO: vertically center based on Panel height */} - - + + {stringGetter({ key: STRING_KEYS.GOVERNANCE_DESCRIPTION })} + e.stopPropagation()}> + {stringGetter({ key: STRING_KEYS.LEARN_MORE })} → + + {stringGetter({ key: STRING_KEYS.STAKING })}} + slotRight={panelArrow} onClick={() => dispatch(openDialog({ type: DialogTypes.ExternalNavKeplr }))} > - - - {stringGetter({ key: STRING_KEYS.STAKING_DESCRIPTION })} - e.stopPropagation()}> - {stringGetter({ key: STRING_KEYS.LEARN_MORE })} → - - - {/* TODO: vertically center based on Panel height */} - - + + {stringGetter({ key: STRING_KEYS.STAKING_DESCRIPTION })} + e.stopPropagation()}> + {stringGetter({ key: STRING_KEYS.LEARN_MORE })} → + + {isNotTablet && ( @@ -191,61 +92,25 @@ const Styled: Record = {}; Styled.Page = styled.div` ${layoutMixins.contentContainerPage} gap: 1.5rem; - - @media ${breakpoints.tablet} { - padding: 1rem; - } `; Styled.Panel = styled(Panel)` - padding: 0 1.5rem 1rem; - - @media ${breakpoints.tablet} { - max-width: calc(100vw - 2rem); - } + padding: 1rem 1.5rem; `; -Styled.Row = styled.div` - ${layoutMixins.spacedRow} - gap: 1rem; - - align-items: center; +Styled.Title = styled.h3` + font: var(--font-medium-book); + color: var(--color-text-2); + padding: 1rem 1.5rem 0; `; Styled.Description = styled.div` color: var(--color-text-0); - - a { - color: var(--color-text-1); - } + --link-color: var(--color-text-1); `; -Styled.Migrate = styled.section` - max-width: min(100vw, var(--content-max-width)); - - padding: 1.5rem; - - background-color: var(--color-layer-3); - border-radius: 0.875rem; -`; - -Styled.TwoItemRow = styled(Styled.Row)` - grid-template-columns: 1fr 1fr; -`; - -Styled.MigrateAction = styled(Styled.TwoItemRow)` - padding: 1rem; - - background-color: var(--color-layer-2); - border: solid var(--border-width) var(--color-border); - border-radius: 0.75rem; -`; - -Styled.Token = styled(Output)` - font: var(--font-large-book); -`; - -Styled.PanelRow = styled(Styled.Row)` +Styled.PanelRow = styled.div` + ${layoutMixins.spacedRow} gap: 1.5rem; max-width: min(100vw, var(--content-max-width)); align-items: flex-start; @@ -269,65 +134,11 @@ Styled.BalancePanelContainer = styled.div` } `; -Styled.Title = styled.h3` - ${layoutMixins.inlineRow} - padding: 1.25rem 1.5rem 0.5rem; - - font: var(--font-medium-book); - color: var(--color-text-2); -`; - -Styled.MigrateTitle = styled(Styled.Title)` - padding: 0 0 0.5rem; -`; - -Styled.MobileMigrateCard = styled(Styled.Panel)` - ${layoutMixins.flexColumn} - gap: 1rem; - - align-items: center; -`; - -Styled.MobileMigrateHeader = styled(Styled.Title)` - ${layoutMixins.inlineRow} - gap: 1ch; - padding-bottom: 1rem; - - font: var(--font-small-book); - color: var(--color-text-0); - - h3 { - ${layoutMixins.inlineRow} - font: var(--font-large-book); - color: var(--color-text-2); - - svg { - font-size: 1.75rem; - } - } - - span { - margin-top: 0.2rem; - b { - font-weight: var(--fontWeight-book); - color: var(--color-text-1); - } - } -`; - -Styled.Details = styled(Details)` - padding: 0.5rem 1rem; -`; - -Styled.WithReceipt = styled(WithReceipt)` - width: 100%; -`; - -Styled.LearnMore = styled(Styled.Description)` - ${layoutMixins.row} - gap: 1ch; -`; - Styled.IconButton = styled(IconButton)` color: var(--color-text-0); + --color-border: var(--color-layer-6); +`; + +Styled.Arrow = styled.div` + padding: 1rem 1.5rem; `; diff --git a/src/views/dialogs/ExternalNavKeplrDialog.tsx b/src/views/dialogs/ExternalNavKeplrDialog.tsx index 505d2a2..02b6da2 100644 --- a/src/views/dialogs/ExternalNavKeplrDialog.tsx +++ b/src/views/dialogs/ExternalNavKeplrDialog.tsx @@ -104,4 +104,5 @@ Styled.Button = styled(Button)` Styled.IconButton = styled(IconButton)` color: var(--color-text-0); + --color-border: var(--color-layer-6); `; From d92b49f4fa55b7955bb1635e3e5d709de44e1ddd Mon Sep 17 00:00:00 2001 From: aleka Date: Fri, 27 Oct 2023 16:47:34 -0400 Subject: [PATCH 4/6] bump packages, fix missing asset symbol (#106) --- package.json | 4 ++-- pnpm-lock.yaml | 24 ++++++++++++------------ src/pages/trade/TradeHeaderMobile.tsx | 4 ++-- src/views/tables/OrdersTable.tsx | 6 +++--- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 6037140..da38c55 100644 --- a/package.json +++ b/package.json @@ -40,8 +40,8 @@ "@cosmjs/stargate": "^0.31.0", "@cosmjs/tendermint-rpc": "^0.31.0", "@dydxprotocol/v4-abacus": "^1.0.3", - "@dydxprotocol/v4-client-js": "^0.40.3", - "@dydxprotocol/v4-localization": "^0.1.32", + "@dydxprotocol/v4-client-js": "^1.0.0", + "@dydxprotocol/v4-localization": "^1.0.0", "@ethersproject/providers": "^5.7.2", "@js-joda/core": "^5.5.3", "@radix-ui/react-collapsible": "^1.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 65dbd3a..e1339bb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,9 +1,5 @@ lockfileVersion: '6.0' -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - dependencies: '@0xsquid/sdk': specifier: ^1.10.0 @@ -30,11 +26,11 @@ dependencies: specifier: ^1.0.3 version: 1.0.3 '@dydxprotocol/v4-client-js': - specifier: ^0.40.3 - version: 0.40.3 + specifier: ^1.0.0 + version: 1.0.0 '@dydxprotocol/v4-localization': - specifier: ^0.1.32 - version: 0.1.32 + specifier: ^1.0.0 + version: 1.0.0 '@ethersproject/providers': specifier: ^5.7.2 version: 5.7.2 @@ -983,8 +979,8 @@ packages: resolution: {integrity: sha512-GuX37/DMMNSke8ZFcw52II7IVJfUgVGHqoi1Uw2cUb+hgIjjSG3OtbyRWedm5r6nqWq8BNLOexI0VVFB6OMVYg==} dev: false - /@dydxprotocol/v4-client-js@0.40.3: - resolution: {integrity: sha512-nMQd6tYisKDKIbfx0BGJSYEOSt+I+t5SsaBSmlgTdso+w2rCRO9vyxS+u6MF9h4w5FsVRfhHo3e6uTWX48WpGQ==} + /@dydxprotocol/v4-client-js@1.0.0: + resolution: {integrity: sha512-ehfHO+zQy795TcJRwtiawadFHZyh4HnpJNP26hCGsIjLE5q6LLHweQHpK/1N/sXU1PBOuQwc7iaJnFop6gYauQ==} dependencies: '@cosmjs/amino': 0.30.1 '@cosmjs/encoding': 0.31.1 @@ -1011,8 +1007,8 @@ packages: - utf-8-validate dev: false - /@dydxprotocol/v4-localization@0.1.32: - resolution: {integrity: sha512-ZtXScxgFLjUt0Ag52RyFnQe9aEl1Aky5fp+vMGOBduVkFiCEMRMkSsSgg6grMdyw/x0AbnxOTRkhYoX2MsK9Ow==} + /@dydxprotocol/v4-localization@1.0.0: + resolution: {integrity: sha512-U7QjOlzpfSAVEchkNDB3xYRx7okzdeYi83XsnHwI+EHa2quFm/2Y2dhrBkT5fqpZmhcwxb/vG8AZmFSToOf9hA==} dev: false /@dydxprotocol/v4-proto@0.4.1: @@ -14100,3 +14096,7 @@ packages: /zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} dev: true + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false diff --git a/src/pages/trade/TradeHeaderMobile.tsx b/src/pages/trade/TradeHeaderMobile.tsx index c3ccdc5..3b895ce 100644 --- a/src/pages/trade/TradeHeaderMobile.tsx +++ b/src/pages/trade/TradeHeaderMobile.tsx @@ -17,7 +17,7 @@ import { MustBigNumber } from '@/lib/numbers'; import { MidMarketPrice } from '@/views/MidMarketPrice'; export const TradeHeaderMobile = () => { - const { name, symbol } = useSelector(getCurrentMarketAssetData, shallowEqual) ?? {}; + const { name, id } = useSelector(getCurrentMarketAssetData, shallowEqual) ?? {}; const navigate = useNavigate(); const { market, priceChange24H, priceChange24HPercent } = @@ -27,7 +27,7 @@ export const TradeHeaderMobile = () => { navigate(AppRoute.Markets)} /> - +

{name}

{market} diff --git a/src/views/tables/OrdersTable.tsx b/src/views/tables/OrdersTable.tsx index 68f018a..0d22cb9 100644 --- a/src/views/tables/OrdersTable.tsx +++ b/src/views/tables/OrdersTable.tsx @@ -231,7 +231,7 @@ const getOrdersTableColumnDef = ({ key: STRING_KEYS.FILL, })}`, renderCell: ({ - asset: { symbol: assetSymbol }, + asset, createdAtMilliseconds, size, status, @@ -254,7 +254,7 @@ const getOrdersTableColumnDef = ({ value={createdAtMilliseconds} /> - + @@ -276,7 +276,7 @@ const getOrdersTableColumnDef = ({ type={OutputType.Asset} value={size} fractionDigits={TOKEN_DECIMALS} - tag={assetSymbol} + tag={asset?.id} /> From e6858ca9176b634407c1fd67c5bfbe6fb8a40c65 Mon Sep 17 00:00:00 2001 From: aleka Date: Fri, 27 Oct 2023 17:39:12 -0400 Subject: [PATCH 5/6] show loading state instead of "Unavailable" for place order button (#104) * show loading instead of unavailable for place order button --- src/views/dialogs/TradeDialog.tsx | 2 +- src/views/forms/TradeForm.tsx | 1 - .../TradeForm/PlaceOrderButtonAndReceipt.tsx | 20 ++++++++++++++----- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/views/dialogs/TradeDialog.tsx b/src/views/dialogs/TradeDialog.tsx index a4190fa..0cd9a14 100644 --- a/src/views/dialogs/TradeDialog.tsx +++ b/src/views/dialogs/TradeDialog.tsx @@ -37,7 +37,7 @@ export const TradeDialog = ({ isOpen, setIsOpen, slotTrigger }: ElementProps) => const selectedTradeType = getSelectedTradeType(type); const { typeOptions } = useSelector(getInputTradeOptions, shallowEqual) ?? {}; - const allTradeTypeItems = typeOptions?.toArray()?.map(({ type, stringKey }) => ({ + const allTradeTypeItems = (typeOptions?.toArray() ?? []).map(({ type, stringKey }) => ({ value: type, label: stringGetter({ key: stringKey as StringKey, diff --git a/src/views/forms/TradeForm.tsx b/src/views/forms/TradeForm.tsx index e67f7c0..352b4ca 100644 --- a/src/views/forms/TradeForm.tsx +++ b/src/views/forms/TradeForm.tsx @@ -322,7 +322,6 @@ export const TradeForm = ({ summary={summary ?? undefined} currentStep={currentStep} showDeposit={inputAlert?.errorAction === TradeInputErrorAction.DEPOSIT} - showConnectWallet={inputAlert?.errorAction === TradeInputErrorAction.CONNECT_WALLET} /> diff --git a/src/views/forms/TradeForm/PlaceOrderButtonAndReceipt.tsx b/src/views/forms/TradeForm/PlaceOrderButtonAndReceipt.tsx index 0a5f280..27844e5 100644 --- a/src/views/forms/TradeForm/PlaceOrderButtonAndReceipt.tsx +++ b/src/views/forms/TradeForm/PlaceOrderButtonAndReceipt.tsx @@ -7,9 +7,8 @@ import { DialogTypes } from '@/constants/dialogs'; import { STRING_KEYS } from '@/constants/localization'; import { TRADE_TYPE_STRINGS, MobilePlaceOrderSteps } from '@/constants/trade'; -import { useStringGetter } from '@/hooks'; +import { useStringGetter, useTokenConfigs } from '@/hooks'; -import { AssetIcon } from '@/components/AssetIcon'; import { Button } from '@/components/Button'; import { Output, OutputType, ShowSign } from '@/components/Output'; import { WithDetailsReceipt } from '@/components/WithDetailsReceipt'; @@ -47,6 +46,7 @@ export const PlaceOrderButtonAndReceipt = ({ }: ElementProps) => { const stringGetter = useStringGetter(); const dispatch = useDispatch(); + const { chainTokenLabel } = useTokenConfigs(); const canAccountTrade = useSelector(calculateCanAccountTrade); const subaccountNumber = useSelector(getSubaccountId); @@ -88,7 +88,14 @@ export const PlaceOrderButtonAndReceipt = ({ {/* */} ), - value: , + value: ( + + ), tooltip: 'max-reward', }, { @@ -111,7 +118,7 @@ export const PlaceOrderButtonAndReceipt = ({ ? actionStringKey : STRING_KEYS.UNAVAILABLE, buttonAction: ButtonAction.Primary, - buttonState: { isDisabled: !shouldEnableTrade }, + buttonState: { isDisabled: !shouldEnableTrade, isLoading: hasMissingData }, }, [MobilePlaceOrderSteps.PreviewOrder]: { @@ -148,7 +155,10 @@ export const PlaceOrderButtonAndReceipt = ({ const buttonState = currentStep ? buttonStatesPerStep[currentStep].buttonState - : { isDisabled: !shouldEnableTrade || isLoading, isLoading }; + : { + isDisabled: !shouldEnableTrade || isLoading, + isLoading: isLoading || hasMissingData, + }; return ( From 2fe6c2bb3b6c4d4c647b90922eb761369614297c Mon Sep 17 00:00:00 2001 From: aleka Date: Fri, 27 Oct 2023 23:32:51 -0400 Subject: [PATCH 6/6] reorder header, center align header, update collapse caret icons (#110) --- src/components/Collapsible.tsx | 2 +- src/components/NavigationMenu.tsx | 3 +++ src/layout/Header/HeaderDesktop.tsx | 33 ++++++++++++++++++++--------- src/views/TransferStatus.tsx | 2 +- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/components/Collapsible.tsx b/src/components/Collapsible.tsx index 56c47f8..84c3c13 100644 --- a/src/components/Collapsible.tsx +++ b/src/components/Collapsible.tsx @@ -80,7 +80,7 @@ Styled.TriggerIcon = styled.span` width: var(--trigger-icon-width); display: inline-flex; - transition: transform 0.3s var(--ease-out-expo); + transition: rotate 0.3s var(--ease-out-expo); color: var(--trigger-icon-color); ${Styled.Trigger}[data-state='open'] & { diff --git a/src/components/NavigationMenu.tsx b/src/components/NavigationMenu.tsx index 1e2f16e..d52cde2 100644 --- a/src/components/NavigationMenu.tsx +++ b/src/components/NavigationMenu.tsx @@ -525,6 +525,9 @@ Styled.NavItem = styled(NavItem)<{ orientation: 'horizontal' | 'vertical' }>` `; Styled.Icon = styled(Icon)` + height: 0.75em; + transition: rotate 0.3s var(--ease-out-expo); + ${Styled.List}[data-orientation="menu"] & { rotate: -0.25turn; } diff --git a/src/layout/Header/HeaderDesktop.tsx b/src/layout/Header/HeaderDesktop.tsx index 464c6c7..3ceba10 100644 --- a/src/layout/Header/HeaderDesktop.tsx +++ b/src/layout/Header/HeaderDesktop.tsx @@ -24,6 +24,7 @@ import { openDialog } from '@/state/dialogs'; import { headerMixins } from '@/styles/headerMixins'; import { layoutMixins } from '@/styles/layoutMixins'; +import breakpoints from '@/styles/breakpoints'; export const HeaderDesktop = () => { const stringGetter = useStringGetter(); @@ -34,26 +35,26 @@ export const HeaderDesktop = () => { { group: 'navigation', items: [ - { - value: 'MARKET', - label: stringGetter({ key: STRING_KEYS.MARKET }), - href: AppRoute.Markets, - }, { value: 'TRADE', label: stringGetter({ key: STRING_KEYS.TRADE }), href: AppRoute.Trade, }, - { - value: chainTokenLabel, - label: chainTokenLabel, - href: `/${chainTokenLabel}`, - }, { value: 'PORTFOLIO', label: stringGetter({ key: STRING_KEYS.PORTFOLIO }), href: AppRoute.Portfolio, }, + { + value: 'MARKETS', + label: stringGetter({ key: STRING_KEYS.MARKETS }), + href: AppRoute.Markets, + }, + { + value: chainTokenLabel, + label: chainTokenLabel, + href: `/${chainTokenLabel}`, + }, { value: 'MORE', label: stringGetter({ key: STRING_KEYS.MORE }), @@ -150,6 +151,7 @@ const Styled: Record = {}; Styled.Header = styled.header` --header-horizontal-padding-mobile: 0.5rem; + --trigger-height: 2.25rem; --logo-width: 3.5rem; ${layoutMixins.container} @@ -157,6 +159,8 @@ Styled.Header = styled.header` ${layoutMixins.scrollSnapItem} backdrop-filter: none; + height: var(--page-currentHeaderHeight); + grid-area: Header; display: grid; @@ -169,6 +173,14 @@ Styled.Header = styled.header` ) var(--border-width) 1fr var(--border-width) auto; + @media ${breakpoints.tablet} { + --trigger-height: 3rem; + } + + @media ${breakpoints.mobile} { + --navBefore-width: 7rem; + } + font-size: 0.9375rem; :before { @@ -179,6 +191,7 @@ Styled.Header = styled.header` Styled.NavigationMenu = styled(NavigationMenu)` & { --navigationMenu-height: var(--stickyArea-topHeight); + --navigationMenu-item-height: var(--trigger-height); } ${layoutMixins.scrollArea} diff --git a/src/views/TransferStatus.tsx b/src/views/TransferStatus.tsx index 81868cf..b54cd01 100644 --- a/src/views/TransferStatus.tsx +++ b/src/views/TransferStatus.tsx @@ -168,7 +168,7 @@ Styled.TriggerIcon = styled.span` width: 0.75em; display: inline-flex; - transition: transform 0.3s var(--ease-out-expo); + transition: rotate 0.3s var(--ease-out-expo); ${Styled.Trigger}[data-state='open'] & { rotate: -0.5turn;