Compare commits

..
Author SHA1 Message Date
Aleka Cheung b0946688b1 add more controlled pagination to table 2024-02-05 18:48:09 -05:00
95 changed files with 1192 additions and 3340 deletions
-7
View File
@@ -8,14 +8,7 @@ VITE_V3_TOKEN_ADDRESS=
VITE_TOKEN_MIGRATION_URI=
AMPLITUDE_API_KEY=
AMPLITUDE_SERVER_URL=
BUGSNAG_API_KEY=
IOS_APP_ID=
INTERCOM_APP_ID=
STATUS_PAGE_SCRIPT_URI=
SMARTBANNER_APP_NAME=
SMARTBANNER_ORG_NAME=
SMARTBANNER_ICON_URL=
SMARTBANNER_APPSTORE_URL=
SMARTBANNER_GOOGLEPLAY_URL=
-1
View File
@@ -39,7 +39,6 @@ jobs:
pnpm run build:inject-amplitude
pnpm run build:inject-bugsnag
pnpm run build:inject-statuspage
pnpm run build:inject-smartbanner
sh scripts/inject-app-deeplinks.sh
- name: Upload to IPFS via web3.storage
+8 -53
View File
@@ -2,25 +2,15 @@ import '@/polyfills';
import { useEffect, useState } from 'react';
import { Provider } from 'react-redux';
import styled from 'styled-components';
import { WagmiConfig } from 'wagmi';
import { GrazProvider } from 'graz';
import { QueryClient, QueryClientProvider } from 'react-query';
import { SupportedLocales } from '@/constants/localization';
import { AccountsProvider } from '@/hooks/useAccounts';
import { AppThemeAndColorModeProvider } from '@/hooks/useAppThemeAndColorMode';
import { DydxProvider } from '@/hooks/useDydxClient';
import { DialogAreaProvider } from '@/hooks/useDialogArea';
import { LocaleProvider } from '@/hooks/useLocaleSeparators';
import { PotentialMarketsProvider } from '@/hooks/usePotentialMarkets';
import { RestrictionProvider } from '@/hooks/useRestrictions';
import { SubaccountProvider } from '@/hooks/useSubaccount';
import { store } from '@/state/_store';
import { GlobalStyle } from '@/styles/globalStyle';
import { SelectMenu, SelectItem } from '@/components/SelectMenu';
import { AppThemeAndColorModeProvider } from '@/hooks/useAppThemeAndColorMode';
import {
AppTheme,
AppThemeSystemSetting,
@@ -28,38 +18,11 @@ import {
setAppThemeSetting,
setAppColorMode,
} from '@/state/configs';
import { setLocaleLoaded, setSelectedLocale } from '@/state/localization';
import { store } from '@/state/_store';
import { config } from '@/lib/wagmi';
import { setLocaleLoaded } from '@/state/localization';
import '@/index.css';
import './ladle.css';
const queryClient = new QueryClient();
const wrapProvider = (Component: React.ComponentType<any>, props?: any) => {
// eslint-disable-next-line react/display-name
return ({ children }: { children: React.ReactNode }) => (
<Component {...props}>{children}</Component>
);
};
const providers = [
wrapProvider(QueryClientProvider, { client: queryClient }),
wrapProvider(GrazProvider),
wrapProvider(WagmiConfig, { config }),
wrapProvider(LocaleProvider),
wrapProvider(RestrictionProvider),
wrapProvider(DydxProvider),
wrapProvider(AccountsProvider),
wrapProvider(SubaccountProvider),
wrapProvider(DialogAreaProvider),
wrapProvider(PotentialMarketsProvider),
wrapProvider(AppThemeAndColorModeProvider),
];
export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [theme, setTheme] = useState(AppTheme.Classic);
const [colorMode, setColorMode] = useState(AppColorMode.GreenUp);
@@ -70,20 +33,9 @@ export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children
}, [theme, colorMode]);
useEffect(() => {
store.dispatch(setSelectedLocale({ locale: SupportedLocales.EN }));
store.dispatch(setLocaleLoaded(true));
}, []);
const content = [...providers].reverse().reduce(
(children, Provider) => {
return <Provider>{children}</Provider>;
},
<StoryContent>
<GlobalStyle />
{children}
</StoryContent>
);
return (
<Provider store={store}>
<StoryHeader>
@@ -127,7 +79,10 @@ export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children
</SelectMenu>
</StoryHeader>
<hr />
{content}
<AppThemeAndColorModeProvider>
<GlobalStyle />
<StoryContent>{children}</StoryContent>
</AppThemeAndColorModeProvider>
</Provider>
);
};
+1 -5
View File
@@ -78,12 +78,11 @@ Set environment variables via `.env`.
- `VITE_V3_TOKEN_ADDRESS` (optional): Address of the V3 $DYDX token.
- `VITE_TOKEN_MIGRATION_URI` (optional): The URL of the token migration website.
- `AMPLITUDE_API_KEY` (optional): Amplitude API key for enabling Amplitude; used with `pnpm run build:inject-amplitude`.
- `AMPLITUDE_SERVER_URL` (optional): Custom Amplitude server URL
- `BUGSNAG_API_KEY` (optional): API key for enabling Bugsnag; used with `pnpm run build:inject-bugsnag`.
- `IOS_APP_ID` (optional): iOS app ID used for enabling deep linking to the iOS app; used with `pnpm run build:inject-app-deeplinks`.
- `INTERCOM_APP_ID` (optional): Used for enabling Intercom; utilized with `pnpm run build:inject-intercom`.
- `STATUS_PAGE_SCRIPT_URI` (optional): Used for enabling the status page; used with `pnpm run build:inject-statuspage`.
- `SMARTBANNER_APP_NAME`, `SMARTBANNER_ORG_NAME`, `SMARTBANNER_ICON_URL`, `SMARTBANNER_APPSTORE_URL` (optional): Used for enabling the smart app banner; used with `pnpm run build:inject-smartbanner`.
# Deployments
@@ -107,9 +106,6 @@ pnpm run build --mode testnet
If you wish to incorporate analytics via Amplitude and Bugsnag, you can use our scripts:
`pnpm run build:inject-amplitude` and `pnpm run build:inject-bugsnag`. You will need to provide your own API keys for these services. In the Environment Variables section, name the variables as `AMPLITUDE_API_KEY` and `BUGSNAG_API_KEY` and provide the respective keys as their values.
If you wish to incorporate smart banner for iOS and/or Android apps, you can use our scripts:
`pnpm run build:inject-smartbanner`. You will need to provide your own app configurations for these services. In the Environment Variables section, name the variables as `SMARTBANNER_APP_NAME`, `SMARTBANNER_ORG_NAME`, `SMARTBANNER_ICON_URL` and `SMARTBANNER_APPSTORE_URL` or `SMARTBANNER_GOOGLEPLAY_URL` and provide the respective values.
For more details, check out Vercel's [official documentation](https://vercel.com/docs).
## Deploying to IPFS
+3 -4
View File
@@ -15,7 +15,6 @@
"build:inject-bugsnag": "node scripts/inject-bugsnag.js",
"build:inject-intercom": "node scripts/inject-intercom.js",
"build:inject-statuspage": "node scripts/inject-statuspage.js",
"build:inject-smartbanner": "node scripts/inject-smartbanner.js",
"deploy:ipfs": "node scripts/upload-ipfs.js --verbose",
"deploy:update-ipns": "node scripts/update-ipns.js",
"deploy:update-dnslink": "node scripts/update-dnslink.js",
@@ -40,9 +39,9 @@
"@cosmjs/proto-signing": "^0.32.1",
"@cosmjs/stargate": "^0.32.1",
"@cosmjs/tendermint-rpc": "^0.32.1",
"@dydxprotocol/v4-abacus": "^1.4.2",
"@dydxprotocol/v4-abacus": "^1.4.0",
"@dydxprotocol/v4-client-js": "^1.0.20",
"@dydxprotocol/v4-localization": "^1.1.26",
"@dydxprotocol/v4-localization": "^1.1.22",
"@ethersproject/providers": "^5.7.2",
"@js-joda/core": "^5.5.3",
"@radix-ui/react-accordion": "^1.1.2",
@@ -118,7 +117,7 @@
},
"devDependencies": {
"@babel/core": "^7.22.5",
"@ladle/react": "^4.0.2",
"@ladle/react": "^2.15.0",
"@types/color": "^3.0.3",
"@types/crypto-js": "^4.1.1",
"@types/luxon": "^3.3.0",
+717 -1858
View File
File diff suppressed because it is too large Load Diff
-22
View File
@@ -1,22 +0,0 @@
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "exchange.dydx.trading.debug",
"sha256_cert_fingerprints": [
"8A:9C:CC:49:B0:35:9A:91:67:CB:98:B0:B5:87:92:5F:9E:B7:EF:CE:A0:47:57:85:A4:35:3E:0C:E1:56:9E:A2"
]
}
},
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "exchange.dydx.trading",
"sha256_cert_fingerprints": [
"B2:2D:CC:27:9D:52:05:98:63:C9:7B:34:36:70:A3:8E:00:31:28:08:2D:2E:70:76:C9:31:AE:F9:55:21:15:A5"
]
}
}
]
+2 -75
View File
@@ -93,10 +93,8 @@
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
@@ -124,9 +122,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
}
},
"dydxprotocol-dev-2": {
@@ -177,10 +172,8 @@
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
@@ -208,9 +201,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
}
},
"dydxprotocol-dev-4": {
@@ -262,10 +252,8 @@
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
@@ -293,9 +281,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
}
},
"dydxprotocol-dev-5": {
@@ -346,10 +331,8 @@
"documentation": "https://docs.dydx.exchange/",
"community": "https://discord.com/invite/dydx",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
@@ -377,9 +360,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
}
},
"dydxprotocol-staging": {
@@ -432,10 +412,8 @@
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
@@ -463,9 +441,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
}
},
"dydxprotocol-staging-forced-update": {
@@ -513,8 +488,7 @@
"documentation": "https://v4-teacher.vercel.app/",
"community": "https://discord.com/invite/dydx",
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
"blogs": "https://www.dydx.foundation/blog",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals"
"blogs": "https://www.dydx.foundation/blog"
},
"wallets": {
"walletconnect": {
@@ -547,9 +521,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
}
},
"dydxprotocol-staging-west": {
@@ -602,10 +573,8 @@
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
@@ -633,9 +602,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": true
}
},
"dydxprotocol-testnet": {
@@ -692,10 +658,8 @@
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
@@ -723,9 +687,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-dydx": {
@@ -779,10 +740,8 @@
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
@@ -810,9 +769,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-nodefleet": {
@@ -866,10 +822,8 @@
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
@@ -897,9 +851,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-kingnodes": {
@@ -953,10 +904,8 @@
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
@@ -984,9 +933,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-liquify": {
@@ -1040,10 +986,8 @@
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnMore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnMore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
},
@@ -1071,9 +1015,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-polkachu": {
@@ -1122,8 +1063,7 @@
"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",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals"
"blogs": "https://www.dydx.foundation/blog"
},
"wallets": {
"walletconnect": {
@@ -1149,9 +1089,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": false
}
},
"dydxprotocol-testnet-bware": {
@@ -1205,10 +1142,8 @@
"reduceOnlyLearnmore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
"governanceLearnmore": "https://help.dydx.exchange",
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
"stakingLearnmore": "https://help.dydx.exchange",
"keplrDashboard": "https://testnet.keplr.app/",
"strideZoneApp": "https://testnet.stride.zone",
"accountExportLearnmore": "https://help.dydx.exchange",
"walletLearnmore": "https://www.dydx.academy/video/defi-wallet"
},
@@ -1236,9 +1171,6 @@
"delayBlocks": 900,
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
}
},
"featureFlags": {
"reduceOnlySupported": false
}
},
"dydxprotocol-mainnet": {
@@ -1292,10 +1224,8 @@
"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]",
"newMarketProposalLearnMore": "[HTTP link to new market proposal learn more, can be null]",
"stakingLearnMore": "[HTTP link to staking learn more, can be null]",
"keplrDashboard": "[HTTP link to keplr dashboard, can be null]",
"strideZoneApp": "[HTTP link to stride zone app, can be null]",
"accountExportLearnMore": "[HTTP link to account export learn more, can be null]",
"walletLearnMore": "[HTTP link to wallet learn more, can be null]"
},
@@ -1323,9 +1253,6 @@
"delayBlocks": 0,
"newMarketsMethodology": "[URL to spreadsheet or document that explains methodology]"
}
},
"featureFlags": {
"reduceOnlySupported": false
}
}
}
-7
View File
@@ -176,13 +176,6 @@
"whitepaperLink": "https://dfinity.org/whitepaper.pdf",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/internet-computer/"
},
"JUP-USD": {
"name": "Jupiter",
"tags": ["Defi"],
"websiteLink": "https://station.jup.ag/",
"whitepaperLink": "https://station.jup.ag/blog/green-paper",
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/jupiter-ag/"
},
"LDO-USD": {
"name": "Lido DAO",
"tags": ["Defi"],
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

-15
View File
@@ -1,15 +0,0 @@
<!-- Smartbanner: Configure the mobile app -->
<meta name="smartbanner:title" content="SMARTBANNER_APP_NAME">
<meta name="smartbanner:author" content="SMARTBANNER_ORG_NAME">
<meta name="smartbanner:icon-apple" content="SMARTBANNER_ICON_URL">
<meta name="smartbanner:icon-google" content="SMARTBANNER_ICON_URL">
<!-- Smartbanner: The rest of the configurations can be kept as is -->
<meta name="smartbanner:price" content="FREE">
<meta name="smartbanner:price-suffix-apple" content=" - On the App Store">
<meta name="smartbanner:price-suffix-google" content=" - In Google Play">
<meta name="smartbanner:button" content="VIEW">
<meta name="smartbanner:close-label" content="Close">
<meta name="smartbanner:exclude-user-agent-regex" content="^.*(Windows NT|Intel Mac OS X).*$">
<script src="https://cdn.jsdelivr.net/npm/smartbanner.js@1.22.0/dist/smartbanner.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/smartbanner.js@1.22.0/dist/smartbanner.min.css" rel="stylesheet">
<!-- Smartbanner: End configuration -->
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

-14
View File
@@ -36,17 +36,3 @@ Customize Intercom Messenger by adding logo and brand colors
3. Add API key in Github > Secrets and Variables > Actions as `INTERCOM_APP_ID`
4. In your deploy scripts add `pnpm run build:inject-intercom` after your pnpm build / vite build command.
5. If you are using with the Amplitude deployment scripts, your build command may look like the following: `pnpm build && pnpm run build:inject-amplitude && pnpm run build:inject-intercom`
### Smartbanner
Smartbanner to show download links to iOS and/or Android native apps on mobile devices.
<b>To use with dydxprotocol/v4-web:</b>
1. iOS app App Store link or Android app Google Play link.
2. Add configurations in Github > Secrets and Variables > Actions as
`SMARTBANNER_APP_NAME` for app name
`SMARTBANNER_ORG_NAME` for organization name
`SMARTBANNER_ICON_URL` for icon image
`SMARTBANNER_APPSTORE_URL` for iOS App Store link
`SMARTBANNER_GOOGLEPLAY_URL` for Android Google Play link
3. In your deploy scripts add `pnpm run build:inject-smartbanner` after your pnpm build / vite build command.
4. If you are using with the Amplitude deployment scripts, your build command may look like the following: `pnpm build && pnpm run build:inject-smartbanner`
+3 -30
View File
@@ -3,13 +3,12 @@ import path from 'path';
import { fileURLToPath } from 'url';
const AMPLITUDE_API_KEY = process.env.AMPLITUDE_API_KEY;
const AMPLITUDE_SERVER_URL = process.env.AMPLITUDE_SERVER_URL;
const currentPath = fileURLToPath(import.meta.url);
const projectRoot = path.dirname(currentPath);
const htmlFilePath = path.resolve(projectRoot, '../dist/index.html');
if (AMPLITUDE_API_KEY) {
if(AMPLITUDE_API_KEY){
try {
const html = await fs.readFile(htmlFilePath, 'utf-8');
@@ -19,34 +18,8 @@ if (AMPLITUDE_API_KEY) {
`;
const amplitudeListenerScript = `<script type="module">
!(function () {
var e = "${AMPLITUDE_API_KEY}";
e &&
(globalThis.amplitude.init(e${
AMPLITUDE_SERVER_URL
? `, undefined, {
serverUrl: "${AMPLITUDE_SERVER_URL}"
}`
: ''
}),
globalThis.amplitude.setOptOut(!1),
globalThis.addEventListener("dydx:track", function (e) {
var t = e.detail.eventType,
d = e.detail.eventData;
globalThis.amplitude.track(t, d);
}),
globalThis.addEventListener("dydx:identify", function (e) {
var t = e.detail.property,
d = e.detail.propertyValue;
if ("walletAddress" === t) globalThis.amplitude.setUserId(d);
else {
var i = new globalThis.amplitude.Identify();
i.set(t, d), globalThis.amplitude.identify(i);
}
}),
console.log("Amplitude enabled."));
})();
</script>`;
!function(){var e="${AMPLITUDE_API_KEY}";e&&(globalThis.amplitude.init(e),globalThis.amplitude.setOptOut(!1),globalThis.addEventListener("dydx:track",function(e){var t=e.detail.eventType,d=e.detail.eventData;globalThis.amplitude.track(t,d)}),globalThis.addEventListener("dydx:identify",function(e){var t=e.detail.property,d=e.detail.propertyValue;if("walletAddress"===t)globalThis.amplitude.setUserId(d);else{var i=new globalThis.amplitude.Identify;i.set(t,d),globalThis.amplitude.identify(i)}}),console.log("Amplitude enabled."))}();
</script>`;
const injectedHtml = html.replace(
'<div id="root"></div>',
-60
View File
@@ -1,60 +0,0 @@
/* eslint-disable no-console */
import fs from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';
const SMARTBANNER_APP_NAME = process.env.SMARTBANNER_APP_NAME;
const SMARTBANNER_ORG_NAME = process.env.SMARTBANNER_ORG_NAME;
const SMARTBANNER_ICON_URL = process.env.SMARTBANNER_ICON_URL;
const SMARTBANNER_APPSTORE_URL = process.env.SMARTBANNER_APPSTORE_URL;
const SMARTBANNER_GOOGLEPLAY_URL = process.env.SMARTBANNER_GOOGLEPLAY_URL;
const currentPath = fileURLToPath(import.meta.url);
const projectRoot = path.dirname(currentPath);
const htmlFilePath = path.resolve(projectRoot, '../dist/index.html');
const smartbannerFilePath = path.resolve(projectRoot, '../dist/smartbanner.html');
if (
SMARTBANNER_APP_NAME &&
SMARTBANNER_ORG_NAME &&
SMARTBANNER_ICON_URL &&
(SMARTBANNER_APPSTORE_URL || SMARTBANNER_GOOGLEPLAY_URL)
) {
try {
const html = await fs.readFile(htmlFilePath, 'utf-8');
let smartbanner = await fs.readFile(smartbannerFilePath, 'utf-8');
smartbanner = smartbanner
.replace('SMARTBANNER_APP_NAME', SMARTBANNER_APP_NAME)
.replace('SMARTBANNER_ORG_NAME', SMARTBANNER_ORG_NAME)
.replace('SMARTBANNER_ICON_URL', SMARTBANNER_ICON_URL)
.replace('SMARTBANNER_ICON_URL', SMARTBANNER_ICON_URL);
/* hardcoded injection depending on whether the app is available on App Store and/or Google Play */
if (SMARTBANNER_APPSTORE_URL) {
smartbanner = `\t<meta name="smartbanner:button-url-apple" content="${SMARTBANNER_APPSTORE_URL}">\n` + smartbanner;
}
if (SMARTBANNER_GOOGLEPLAY_URL) {
smartbanner = `\t<meta name="smartbanner:button-url-google" content="${SMARTBANNER_GOOGLEPLAY_URL}">\n` + smartbanner;
}
if (SMARTBANNER_APPSTORE_URL) {
if (SMARTBANNER_GOOGLEPLAY_URL) {
smartbanner = `\t<meta name="smartbanner:enabled-platforms" content="android,ios">\n` + smartbanner;
} else {
smartbanner = `\t<meta name="smartbanner:enabled-platforms" content="ios">\n` + smartbanner;
}
} else {
if (SMARTBANNER_GOOGLEPLAY_URL) {
smartbanner = `\t<meta name="smartbanner:enabled-platforms" content="android">\n` + smartbanner;
}
}
const injectedHtml = html.replace('</head>', `${smartbanner}\n</head>`);
await fs.writeFile(htmlFilePath, injectedHtml, 'utf-8');
console.log('Smartbanner scripts successfully injected.');
} catch (err) {
console.error('Error injecting Smartbanner scripts:', err);
}
}
+2 -3
View File
@@ -52,9 +52,9 @@ const AlertsPage = lazy(() => import('@/pages/AlertsPage'));
const ProfilePage = lazy(() => import('@/pages/Profile'));
const SettingsPage = lazy(() => import('@/pages/settings/Settings'));
const TradePage = lazy(() => import('@/pages/trade/Trade'));
const RewardsPage = lazy(() => import('@/pages/rewards/RewardsPage'));
const TermsOfUsePage = lazy(() => import('@/pages/TermsOfUsePage'));
const PrivacyPolicyPage = lazy(() => import('@/pages/PrivacyPolicyPage'));
const TokenPage = lazy(() => import('@/pages/token/Token'));
const queryClient = new QueryClient();
@@ -87,7 +87,7 @@ const Content = () => {
<Route path={MarketsRoute.New} element={<NewMarket />} />
<Route path={AppRoute.Markets} element={<MarketsPage />} />
</Route>
<Route path={`/${chainTokenLabel}/*`} element={<TokenPage />} />
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
{isTablet && (
<>
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
@@ -207,7 +207,6 @@ Styled.Content = styled.div<{ isShowingHeader: boolean; isShowingFooter: boolean
Styled.Main = styled.main`
${layoutMixins.contentSectionAttached}
box-shadow: none;
grid-area: Main;
+3
View File
@@ -40,6 +40,9 @@ const AlertContainer = styled.div<StyleProps>`
case AlertType.Info: {
return css`
--alert-accent-color: var(--color-text-1);
--alert-default-background-opacity: 0.133; // Relative
// --alert-background: var(--color-layer-6); // Absolute
`;
}
case AlertType.Success: {
-1
View File
@@ -31,7 +31,6 @@ const assetIcons = {
ETH: '/currencies/eth.png',
FIL: '/currencies/fil.png',
ICP: '/currencies/icp.png',
JUP: '/currencies/jup.png',
LDO: '/currencies/ldo.png',
LINK: '/currencies/link.png',
LTC: '/currencies/ltc.png',
+3 -3
View File
@@ -103,14 +103,14 @@ const buttonActionVariants = {
[ButtonAction.Create]: css`
--button-textColor: var(--color-text-button);
--button-backgroundColor: var(--color-green);
--button-backgroundColor: var(--color-success);
--button-border: solid var(--border-width) var(--color-border-white);
--button-hover-filter: brightness(var(--hover-filter-variant));
`,
[ButtonAction.Destroy]: css`
--button-textColor: var(--color-text-button);
--button-backgroundColor: var(--color-red);
--button-backgroundColor: var(--color-error);
--button-border: solid var(--border-width) var(--color-border-white);
--button-hover-filter: brightness(var(--hover-filter-variant));
`,
@@ -122,7 +122,7 @@ const buttonActionVariants = {
`,
[ButtonAction.Reset]: css`
--button-textColor: var(--color-red);
--button-textColor: var(--color-error);
--button-backgroundColor: var(--color-layer-3);
--button-border: solid var(--border-width) var(--color-border-red);
--button-hover-filter: brightness(var(--hover-filter-variant));
+9 -13
View File
@@ -6,7 +6,6 @@ import { layoutMixins } from '@/styles/layoutMixins';
type ElementProps = {
title: string;
subtitle?: React.ReactNode;
slotLeft?: React.ReactNode;
slotRight?: React.ReactNode;
};
@@ -17,16 +16,14 @@ type StyleProps = {
export const ContentSectionHeader = ({
title,
subtitle,
slotLeft,
slotRight,
className,
}: ElementProps & StyleProps) => (
<Styled.ContentSectionHeader className={className}>
{slotLeft}
<Styled.Header>
<div>
{title && <h3>{title}</h3>}
{subtitle && <p>{subtitle}</p>}
</Styled.Header>
</div>
{slotRight}
</Styled.ContentSectionHeader>
);
@@ -43,15 +40,9 @@ Styled.ContentSectionHeader = styled.header<StyleProps>`
padding: 1rem var(--header-horizontal-padding);
@media ${breakpoints.tablet} {
flex-wrap: wrap;
--header-horizontal-padding: 1.25rem;
> div {
${layoutMixins.column}
}
`;
Styled.Header = styled.div`
${layoutMixins.column}
flex: 1;
h3 {
color: var(--color-text-2);
@@ -63,4 +54,9 @@ Styled.Header = styled.div`
font: var(--font-small-book);
margin-top: 0.25rem;
}
@media ${breakpoints.tablet} {
flex-wrap: wrap;
--header-horizontal-padding: 1.25rem;
}
`;
+23 -38
View File
@@ -7,50 +7,35 @@ import { StoryWrapper } from '.ladle/components';
import styled, { type AnyStyledComponent } from 'styled-components';
import { layoutMixins } from '@/styles/layoutMixins';
export const DetailsStory: Story<Parameters<typeof Details>[0]> = (args) => (
export const DetailsStory: Story<Parameters<typeof Details>> = () => (
<StoryWrapper>
<Styled.Resizable>
<Details {...args} />
<Details
items={[
{
key: 'item-1',
label: 'Item 1',
tooltip: 'leverage',
value: 'Value 1',
},
{
key: 'item-2',
label: 'Really really really long item name 2',
tooltip: 'liquidation-price',
value: 'Value 2',
},
{
key: 'item-3',
label: 'Item 3',
tooltip: 'realized-pnl',
value: 'Value 3',
},
]}
/>
</Styled.Resizable>
</StoryWrapper>
);
DetailsStory.args = {
items: [
{
key: 'item-1',
label: 'Item 1',
tooltip: 'leverage',
value: 'Value 1',
},
{
key: 'item-2',
label: 'Really really really long item name 2',
tooltip: 'liquidation-price',
value: 'Value 2',
},
{
key: 'item-3',
label: 'Item 3',
tooltip: 'realized-pnl',
value: 'Value 3',
},
],
showSubitems: false,
isLoading: false,
withOverflow: false,
withSeparators: false,
};
DetailsStory.argTypes = {
justifyItems: { options: ['start', 'end'], control: { type: 'select' }, defaultValue: 'start' },
layout: {
options: ['column', 'row', 'rowColumns', 'grid', 'stackColumn'],
control: { type: 'select' },
defaultValue: 'column',
},
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Resizable = styled.section`
+13 -13
View File
@@ -4,18 +4,8 @@ import { DropdownMenu } from '@/components/DropdownMenu';
import { StoryWrapper } from '.ladle/components';
export const DropdownMenuStory: Story<Parameters<typeof DropdownMenu>[0]> = (args) => {
return (
<StoryWrapper>
<DropdownMenu {...args}>
<span>Menu</span>
</DropdownMenu>
</StoryWrapper>
);
};
DropdownMenuStory.args = {
items: [
export const DropdownMenuStory: Story<Parameters<typeof DropdownMenu>> = (args) => {
const exampleItems = [
{
value: '0',
label: 'Item 0',
@@ -39,9 +29,19 @@ DropdownMenuStory.args = {
onSelect: () => alert('Item 3 action'),
highlightColor: 'destroy',
},
],
];
return (
<StoryWrapper>
<DropdownMenu {...args} items={exampleItems}>
<span>Menu</span>
</DropdownMenu>
</StoryWrapper>
);
};
DropdownMenuStory.args = {};
DropdownMenuStory.argTypes = {
align: {
options: ['start', 'center', 'end'],
+2 -2
View File
@@ -91,10 +91,10 @@ Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'create' | 'destroy' }>
--item-highlighted-textColor: var(--color-accent);
`,
['create']: `
--item-highlighted-textColor: var(--color-green);
--item-highlighted-textColor: var(--color-success);
`,
['destroy']: `
--item-highlighted-textColor: var(--color-red);
--item-highlighted-textColor: var(--color-error);
`,
}[$highlightColor])}
@@ -28,22 +28,21 @@ const exampleItems = [
},
];
export const DropdownSelectMenuStory: Story<
Pick<Parameters<typeof DropdownSelectMenu>[0], 'items' | 'align' | 'sideOffset' | 'disabled'>
> = (args) => {
export const DropdownSelectMenuStory: Story<Parameters<typeof DropdownSelectMenu>> = (args) => {
const [item, setItem] = useState(exampleItems[0].value);
return (
<StoryWrapper>
<DropdownSelectMenu value={item} onValueChange={(value) => setItem(value)} {...args} />
<DropdownSelectMenu
items={exampleItems}
value={item}
onValueChange={(value) => setItem(value)}
{...args}
/>
</StoryWrapper>
);
};
DropdownSelectMenuStory.args = {
items: exampleItems,
sideOffset: 1,
disabled: false,
};
DropdownSelectMenuStory.args = {};
DropdownSelectMenuStory.argTypes = {
align: {
+1 -1
View File
@@ -4,7 +4,7 @@ import { Icon, IconName } from '@/components/Icon';
import { StoryWrapper } from '.ladle/components';
export const IconStory: Story<Parameters<typeof Icon>[0]> = (args) => {
export const IconStory: Story<Parameters<typeof Icon>> = (args) => {
return (
<StoryWrapper>
<Icon {...args} />
-9
View File
@@ -25,7 +25,6 @@ import {
CoinsIcon,
CommentIcon,
CopyIcon,
CurrencySignIcon,
DepositIcon,
DepthChartIcon,
DiscordIcon,
@@ -36,7 +35,6 @@ import {
FundingChartIcon,
GearIcon,
GiftboxIcon,
GovernanceIcon,
HelpCircleIcon,
HideIcon,
HistoryIcon,
@@ -72,7 +70,6 @@ import {
StarIcon,
SunIcon,
TerminalIcon,
TokenIcon,
TradeIcon,
TransferIcon,
TriangleIcon,
@@ -106,7 +103,6 @@ export enum IconName {
Coins = 'Coins',
Comment = 'Comment',
Copy = 'Copy',
CurrencySign = 'CurrencySign',
Deposit = 'Deposit',
DepthChart = 'DepthChart',
Discord = 'Discord',
@@ -117,7 +113,6 @@ export enum IconName {
FundingChart = 'FundingChart',
Gear = 'Gear',
Giftbox = 'Giftbox',
Governance = 'Governance',
HelpCircle = 'HelpCircle',
Hide = 'Hide',
History = 'History',
@@ -154,7 +149,6 @@ export enum IconName {
Sun = 'Sun',
Terminal = 'Terminal',
TogglesMenu = 'TogglesMenu',
Token = 'Token',
Trade = 'Trade',
Transfer = 'Transfer',
Triangle = 'Triangle',
@@ -188,7 +182,6 @@ const icons = {
[IconName.Coins]: CoinsIcon,
[IconName.Comment]: CommentIcon,
[IconName.Copy]: CopyIcon,
[IconName.CurrencySign]: CurrencySignIcon,
[IconName.Deposit]: DepositIcon,
[IconName.DepthChart]: DepthChartIcon,
[IconName.Discord]: DiscordIcon,
@@ -199,7 +192,6 @@ const icons = {
[IconName.FundingChart]: FundingChartIcon,
[IconName.Gear]: GearIcon,
[IconName.Giftbox]: GiftboxIcon,
[IconName.Governance]: GovernanceIcon,
[IconName.HelpCircle]: HelpCircleIcon,
[IconName.Hide]: HideIcon,
[IconName.History]: HistoryIcon,
@@ -235,7 +227,6 @@ const icons = {
[IconName.Sun]: SunIcon,
[IconName.Terminal]: TerminalIcon,
[IconName.TogglesMenu]: TogglesMenuIcon,
[IconName.Token]: TokenIcon,
[IconName.Trade]: TradeIcon,
[IconName.Transfer]: TransferIcon,
[IconName.Triangle]: TriangleIcon,
+1 -1
View File
@@ -6,7 +6,7 @@ import { Link } from '@/components/Link';
import { StoryWrapper } from '.ladle/components';
import { layoutMixins } from '@/styles/layoutMixins';
export const LinkStory: Story<Parameters<typeof Link>[0]> = (args) => {
export const LinkStory: Story<Parameters<typeof Link>> = (args) => {
return (
<StoryWrapper>
<Styled.Container>
+17 -19
View File
@@ -5,24 +5,8 @@ import { HashRouter } from 'react-router-dom';
import { StoryWrapper } from '.ladle/components';
export const NavigationMenuStory: Story<
Pick<Parameters<typeof NavigationMenu>[0], 'items' | 'orientation' | 'submenuPlacement'>
> = (args) => {
return (
<StoryWrapper>
<HashRouter
children={
<NavigationMenu {...args}>
<span>Menu</span>
</NavigationMenu>
}
/>
</StoryWrapper>
);
};
NavigationMenuStory.args = {
items: [
export const NavigationMenuStory: Story<Parameters<typeof NavigationMenu>> = (args) => {
const exampleItems = [
{
group: 'navigation',
groupLabel: 'Views',
@@ -109,9 +93,23 @@ NavigationMenuStory.args = {
},
],
},
],
];
return (
<StoryWrapper>
<HashRouter
children={
<NavigationMenu {...args} items={exampleItems}>
<span>Menu</span>
</NavigationMenu>
}
/>
</StoryWrapper>
);
};
NavigationMenuStory.args = {};
NavigationMenuStory.argTypes = {
orientation: {
options: ['vertical', 'horizontal'],
+1 -1
View File
@@ -7,7 +7,7 @@ import { StoryWrapper } from '.ladle/components';
import { layoutMixins } from '@/styles/layoutMixins';
import { InputType } from './Input';
export const SearchInputStory: Story<Parameters<typeof SearchInput>[0]> = (args) => (
export const SearchInputStory: Story<Parameters<typeof SearchInput>> = (args) => (
<StoryWrapper>
<Styled.Container>
<SearchInput placeholder="Search something..." type={InputType.Search} />
+5 -2
View File
@@ -6,7 +6,7 @@ import { SearchSelectMenu } from '@/components/SearchSelectMenu';
import { StoryWrapper } from '.ladle/components';
export const SearchSelectMenuStory: Story<Parameters<typeof SearchSelectMenu>[0]> = (args) => {
export const SearchSelectMenuStory: Story<Parameters<typeof SearchSelectMenu>> = (args) => {
const [selectedItem, setSelectedItem] = useState<string>();
const exampleItems = [
@@ -24,7 +24,10 @@ export const SearchSelectMenuStory: Story<Parameters<typeof SearchSelectMenu>[0]
return (
<StoryWrapper>
<Container>
<SearchSelectMenu {...args} items={exampleItems}>
<SearchSelectMenu
{...args}
items={exampleItems}
>
{!selectedItem ? <span>Search and Select</span> : <span>{selectedItem}</span>}
</SearchSelectMenu>
</Container>
+1 -1
View File
@@ -26,7 +26,7 @@ const exampleItems: { value: string; label: string }[] = [
},
];
export const SelectMenuStory: Story<Parameters<typeof SelectMenu>[0]> = (args) => {
export const SelectMenuStory: Story<Parameters<typeof SelectMenu>> = (args) => {
const [value, setValue] = useState(exampleItems[0].value);
const [value2, setValue2] = useState(exampleItems[2].value);
+1 -1
View File
@@ -47,7 +47,7 @@ Styled.Root = styled(Root)`
--switch-thumb-backgroundColor: var(--color-layer-6);
--switch-active-backgroundColor: var(--color-accent);
--switch-active-thumb-backgroundColor: var(--color-white);
--switch-active-thumb-backgroundColor: ${({ theme }) => theme.switchThumbActiveBackground};
position: relative;
width: var(--switch-width);
+20 -19
View File
@@ -13,11 +13,29 @@ enum TabItem {
Item3 = 'Item3',
}
export const TabsStory: Story<Parameters<typeof Tabs>[0]> = (args) => {
const TabItems = [
{
value: TabItem.Item1,
label: 'Item 1',
content: <div>Item 1 Content</div>,
},
{
value: TabItem.Item2,
label: 'Item 2',
content: <div>Item 2 Content</div>,
},
{
value: TabItem.Item3,
label: 'Item 3',
content: <div>Item 3 Content</div>,
},
];
export const TabsStory: Story<Parameters<typeof Tabs>> = (args) => {
return (
<StoryWrapper>
<Styled.Container>
<Tabs {...args} />
<Tabs items={TabItems} {...args} />
</Styled.Container>
</StoryWrapper>
);
@@ -25,23 +43,6 @@ export const TabsStory: Story<Parameters<typeof Tabs>[0]> = (args) => {
TabsStory.args = {
fullWidthTabs: false,
items: [
{
value: TabItem.Item1,
label: 'Item 1',
content: <div>Item 1 Content</div>,
},
{
value: TabItem.Item2,
label: 'Item 2',
content: <div>Item 2 Content</div>,
},
{
value: TabItem.Item3,
label: 'Item 3',
content: <div>Item 3 Content</div>,
},
],
};
TabsStory.argTypes = {
+2 -21
View File
@@ -1,10 +1,10 @@
import type { Story } from '@ladle/react';
import { Tag, TagSign, TagSize, TagType } from '@/components/Tag';
import { Tag } from '@/components/Tag';
import { StoryWrapper } from '.ladle/components';
export const TagStory: Story<Parameters<typeof Tag>[0]> = (args) => {
export const TagStory: Story<Parameters<typeof Tag>> = (args) => {
return (
<StoryWrapper>
<Tag {...args} />
@@ -14,23 +14,4 @@ export const TagStory: Story<Parameters<typeof Tag>[0]> = (args) => {
TagStory.args = {
children: 'USDC',
isHighlighted: false,
};
TagStory.argTypes = {
size: {
options: Object.values(TagSize),
control: { type: 'select' },
defaultValue: TagSize.Small,
},
type: {
options: [...Object.values(TagType), undefined],
control: { type: 'select' },
defaultValue: undefined,
},
sign: {
options: [...Object.values(TagSign), undefined],
control: { type: 'select' },
defaultValue: undefined,
},
};
+8 -8
View File
@@ -1,20 +1,20 @@
import styled, { css } from 'styled-components';
export enum TagSize {
Small = 'Small',
Medium = 'Medium',
Small,
Medium,
}
export enum TagType {
Asset = 'Asset',
Side = 'Side',
Number = 'Number',
Asset,
Side,
Number,
}
export enum TagSign {
Positive = 'Positive',
Negative = 'Negative',
Neutral = 'Neutral',
Positive,
Negative,
Neutral,
}
type StyleProps = {
+1 -1
View File
@@ -5,7 +5,7 @@ import { ButtonShape, ButtonSize } from '@/constants/buttons';
import { StoryWrapper } from '.ladle/components';
import { ToggleButton } from './ToggleButton';
export const ToggleButtonStory: Story<Parameters<typeof ToggleButton>[0]> = (args) => (
export const ToggleButtonStory: Story<Parameters<typeof ToggleButton>> = (args) => (
<StoryWrapper>
<ToggleButton {...args}>Toggle me</ToggleButton>
</StoryWrapper>
+2 -8
View File
@@ -21,22 +21,16 @@ const ToggleGroupItems = [
},
];
export const ToggleGroupStory: Story<
Pick<Parameters<typeof ToggleGroup>[0], 'items' | 'size' | 'shape'>
> = (args) => {
export const ToggleGroupStory: Story<Parameters<typeof ToggleGroup>> = (args) => {
const [value, setValue] = useState('0');
return (
<StoryWrapper>
<ToggleGroup value={value} onValueChange={setValue} {...args} />
<ToggleGroup items={ToggleGroupItems} value={value} onValueChange={setValue} {...args} />
</StoryWrapper>
);
};
ToggleGroupStory.args = {
items: ToggleGroupItems,
};
ToggleGroupStory.argTypes = {
size: {
options: Object.values(ButtonSize),
+2 -2
View File
@@ -117,7 +117,7 @@ Styled.ConfirmButton = styled(Styled.IconButton)`
--button-backgroundColor: hsla(203, 25%, 19%, 1);
svg {
color: var(--color-green);
color: var(--color-success);
}
`;
@@ -125,7 +125,7 @@ Styled.CancelButton = styled(Styled.IconButton)`
--button-backgroundColor: hsla(296, 16%, 18%, 1);
svg {
color: var(--color-red);
color: var(--color-error);
width: 0.8em;
height: 0.8em;
+1 -1
View File
@@ -9,7 +9,7 @@ import { StoryWrapper } from '.ladle/components';
import styled, { type AnyStyledComponent } from 'styled-components';
import { layoutMixins } from '@/styles/layoutMixins';
export const WithLabelStory: Story<Parameters<typeof WithLabel>[0]> = (args) => {
export const WithLabelStory: Story<Parameters<typeof WithLabel>> = (args) => {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
+22 -19
View File
@@ -3,29 +3,32 @@ import type { Story } from '@ladle/react';
import { Button } from '@/components/Button';
import { WithReceipt } from '@/components/WithReceipt';
import { type DetailsItem } from './Details';
import { StoryWrapper } from '.ladle/components';
export const WithReceiptStory: Story<Omit<Parameters<typeof WithReceipt>[0], 'slotReceipt'>> = (
args
) => (
const items: DetailsItem[] = [
{
key: 'item-1',
label: 'Item 1',
value: 'Value 1',
},
{
key: 'item-2',
label: 'Item 2',
value: 'Value 2',
},
{
key: 'item-3',
label: 'Item 3',
value: 'Value 3',
},
];
export const WithReceiptStory: Story<Parameters<WithReceipt>> = (args) => (
<StoryWrapper>
<div style={{ width: 200 }}>
<WithReceipt
slotReceipt={
<div
style={{
padding: '1rem',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
Receipt Content
</div>
}
{...args}
>
<WithReceipt {...args}>
<Button>Hello there</Button>
</WithReceipt>
</div>
@@ -33,7 +36,7 @@ export const WithReceiptStory: Story<Omit<Parameters<typeof WithReceipt>[0], 'sl
);
WithReceiptStory.args = {
hideReceipt: false,
items,
};
WithReceiptStory.argTypes = {
+2 -1
View File
@@ -106,6 +106,8 @@ Styled.Container = styled.div`
--stickyArea1-leftGap: var(--border-width);
min-height: var(--stickyArea-height);
${layoutMixins.withOuterAndInnerBorders}
display: grid;
grid-template: var(--withSidebar-gridTemplate);
`;
@@ -118,7 +120,6 @@ Styled.Side = styled.aside`
${layoutMixins.sticky}
max-height: var(--stickyArea-height);
backdrop-filter: none;
background-color: var(--color-layer-2);
${layoutMixins.stack}
`;
+1 -1
View File
@@ -6,7 +6,7 @@ import { tooltipStrings } from '@/constants/tooltips';
import { StoryWrapper } from '.ladle/components';
export const Tooltip: Story<Parameters<typeof WithTooltip>[0]> = (args) => {
export const Tooltip: Story<Parameters<typeof WithTooltip>> = (args) => {
return (
<StoryWrapper>
<WithTooltip {...args}>
-2
View File
@@ -173,5 +173,3 @@ export type AnalyticsEventData<T extends AnalyticsEvent> =
validatorUrl: string;
}
: never;
export const DEFAULT_TRANSACTION_MEMO = 'dYdX Frontend (web)';
-1
View File
@@ -5,7 +5,6 @@ export enum DialogTypes {
DisplaySettings = 'DisplaySettings',
ExchangeOffline = 'ExchangeOffline',
ExternalLink = 'ExternalLink',
ExternalNavStride = 'ExternalNavStride',
FillDetails = 'FillDetails',
Help = 'Help',
ExternalNavKeplr = 'ExternalNavKeplr',
+60
View File
@@ -1,9 +1,42 @@
export type ExchangeConfigParsedCsv = Array<{
base_asset: string;
exchange: string;
pair: string;
adjust_by_market: string;
min_2_depth: string;
avg_30d_vol: string;
reference_price: string;
risk_assessment: string;
num_oracles: string;
liquidity_tier: string;
asset_name: string;
}>;
export type ExchangeConfigItem = {
exchangeName: string;
ticker: string;
adjustByMarket?: string;
};
export type PotentialMarketParsedCsv = Array<{
base_asset: string;
reference_price: string;
num_oracles: string;
liquidity_tier: string;
asset_name: string;
p: string;
atomic_resolution: string;
min_exchanges: string;
min_price_change_ppm: string;
price_exponent: string;
step_base_quantum: string;
ticksize_exponent: string;
subticks_per_tick: string;
min_order_size: string;
quantum_conversion_exponent: string;
}>;
export type PotentialMarketItem = {
baseAsset: string;
referencePrice: string;
@@ -23,3 +56,30 @@ export type PotentialMarketItem = {
};
export const NUM_ORACLES_TO_QUALIFY_AS_SAFE = 6;
export const LIQUIDITY_TIERS = {
0: {
label: 'Large-cap',
initialMarginFraction: 0.05,
maintenanceMarginFraction: 0.03,
impactNotional: 10_000,
},
1: {
label: 'Mid-cap',
initialMarginFraction: 0.1,
maintenanceMarginFraction: 0.05,
impactNotional: 5_000,
},
2: {
label: 'Long-tail',
initialMarginFraction: 0.2,
maintenanceMarginFraction: 0.1,
impactNotional: 2_500,
},
3: {
label: 'Safety',
initialMarginFraction: 1,
maintenanceMarginFraction: 0.2,
impactNotional: 2_500,
},
};
-6
View File
@@ -29,12 +29,6 @@ export enum HistoryRoute {
Payments = 'payments',
}
export enum TokenRoute {
TradingRewards = 'trading-rewards',
StakingRewards = 'staking-rewards',
Governance = 'governance',
}
export enum MobileSettingsRoute {
Language = 'language',
Notifications = 'notifications',
+2 -8
View File
@@ -5,8 +5,7 @@ export type Theme = {
[AppColorMode.RedUp]: ThemeColorBase;
};
export type ThemeColorBase = BaseColors &
LayerColors &
export type ThemeColorBase = LayerColors &
BorderColors &
TextColors &
GradientColors &
@@ -18,12 +17,6 @@ export type ThemeColorBase = BaseColors &
ComponentColors &
Filters;
type BaseColors = {
white: string;
green: string;
red: string;
};
type LayerColors = {
layer0: string;
layer1: string;
@@ -93,6 +86,7 @@ type IconColors = {
type ComponentColors = {
inputBackground: string;
popoverBackground: string;
switchThumbActiveBackground: string;
toggleBackground: string;
tooltipBackground: string;
};
-1
View File
@@ -40,7 +40,6 @@ export enum WalletErrorType {
// General
ChainMismatch,
UserCanceled,
SwitchChainMethodMissing,
// Non-Deterministic
NonDeterministicWallet,
+1 -3
View File
@@ -16,7 +16,6 @@ import {
import type { ResolutionString } from 'public/tradingview/charting_library';
import type { ConnectNetworkEvent, NetworkConfig } from '@/constants/abacus';
import { DEFAULT_TRANSACTION_MEMO } from '@/constants/analytics';
import { type Candle, RESOLUTION_MAP } from '@/constants/candles';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { DydxChainAsset } from '@/constants/wallets';
@@ -84,8 +83,7 @@ const useDydxClientContext = () => {
{
broadcastPollIntervalMs: 3_000,
broadcastTimeoutMs: 60_000,
},
DEFAULT_TRANSACTION_MEMO
}
)
)
);
+3 -4
View File
@@ -33,7 +33,7 @@ export const useMarketsData = (
return Object.values(allPerpetualMarkets)
.filter(isTruthy)
.map((marketData) => ({
asset: allAssets[marketData.assetId] ?? {},
asset: allAssets[marketData.assetId],
tickSizeDecimals: marketData.configs?.tickSizeDecimals,
...marketData,
...marketData.perpetual,
@@ -46,10 +46,9 @@ export const useMarketsData = (
if (searchFilter) {
return filtered.filter(
({ asset, id }) =>
({ asset }) =>
asset?.name?.toLocaleLowerCase().includes(searchFilter.toLowerCase()) ||
asset?.id?.toLocaleLowerCase().includes(searchFilter.toLowerCase()) ||
id?.toLocaleLowerCase().includes(searchFilter.toLowerCase())
asset?.id?.toLocaleLowerCase().includes(searchFilter.toLowerCase())
);
}
return filtered;
+7 -63
View File
@@ -1,42 +1,18 @@
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
import { createContext, useContext, useEffect, useState } from 'react';
import { STRING_KEYS } from '@/constants/localization';
import type { ExchangeConfigItem, PotentialMarketItem } from '@/constants/potentialMarkets';
import type {
ExchangeConfigItem,
ExchangeConfigParsedCsv,
PotentialMarketItem,
PotentialMarketParsedCsv,
} from '@/constants/potentialMarkets';
import { log } from '@/lib/telemetry';
import { useStringGetter } from './useStringGetter';
const PotentialMarketsContext = createContext<ReturnType<typeof usePotentialMarketsContext>>({
potentialMarkets: undefined,
exchangeConfigs: undefined,
hasPotentialMarketsData: false,
liquidityTiers: {
0: {
label: 'Large-cap',
initialMarginFraction: 0.05,
maintenanceMarginFraction: 0.03,
impactNotional: 10_000,
},
1: {
label: 'Mid-cap',
initialMarginFraction: 0.1,
maintenanceMarginFraction: 0.05,
impactNotional: 5_000,
},
2: {
label: 'Long-tail',
initialMarginFraction: 0.2,
maintenanceMarginFraction: 0.1,
impactNotional: 2_500,
},
3: {
label: 'Safety',
initialMarginFraction: 1,
maintenanceMarginFraction: 0.2,
impactNotional: 2_500,
},
},
});
PotentialMarketsContext.displayName = 'PotentialMarkets';
@@ -51,7 +27,6 @@ const EXCHANGE_CONFIG_FILE_PATH = '/configs/potentialMarketExchangeConfig.json';
const POTENTIAL_MARKETS_FILE_PATH = '/configs/potentialMarketParameters.json';
export const usePotentialMarketsContext = () => {
const stringGetter = useStringGetter();
const [potentialMarkets, setPotentialMarkets] = useState<PotentialMarketItem[]>();
const [exchangeConfigs, setExchangeConfigs] = useState<Record<string, ExchangeConfigItem[]>>();
@@ -79,40 +54,9 @@ export const usePotentialMarketsContext = () => {
}
}, []);
const liquidityTiers = useMemo(
() => ({
0: {
label: stringGetter({ key: STRING_KEYS.LARGE_CAP }),
initialMarginFraction: 0.05,
maintenanceMarginFraction: 0.03,
impactNotional: 10_000,
},
1: {
label: stringGetter({ key: STRING_KEYS.MID_CAP }),
initialMarginFraction: 0.1,
maintenanceMarginFraction: 0.05,
impactNotional: 5_000,
},
2: {
label: stringGetter({ key: STRING_KEYS.LONG_TAIL }),
initialMarginFraction: 0.2,
maintenanceMarginFraction: 0.1,
impactNotional: 2_500,
},
3: {
label: stringGetter({ key: STRING_KEYS.SAFETY }),
initialMarginFraction: 1,
maintenanceMarginFraction: 0.2,
impactNotional: 2_500,
},
}),
[stringGetter]
);
return {
potentialMarkets,
exchangeConfigs,
hasPotentialMarketsData: Boolean(potentialMarkets && exchangeConfigs),
liquidityTiers,
};
};
+17 -21
View File
@@ -5,25 +5,23 @@ 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;
newMarketProposalLearnMore: string;
stakingLearnMore?: string;
keplrDashboard?: string;
strideZoneApp?: string;
accountExportLearnMore?: string;
walletLearnMore?: string;
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 => {
@@ -44,10 +42,8 @@ export const useURLConfigs = (): LinksConfigs => {
documentation: linksConfigs.documentation || FALLBACK_URL,
community: linksConfigs.community || FALLBACK_URL,
governanceLearnMore: linksConfigs.governanceLearnMore || FALLBACK_URL,
newMarketProposalLearnMore: linksConfigs.newMarketProposalLearnMore || FALLBACK_URL,
stakingLearnMore: linksConfigs.stakingLearnMore || FALLBACK_URL,
keplrDashboard: linksConfigs.keplrDashboard || FALLBACK_URL,
strideZoneApp: linksConfigs.strideZoneApp || FALLBACK_URL,
accountExportLearnMore: linksConfigs.accountExportLearnMore || FALLBACK_URL,
walletLearnMore: linksConfigs.walletLearnMore || FALLBACK_URL,
};
+7 -10
View File
@@ -163,20 +163,17 @@ export const useWalletConnection = () => {
}
}
} catch (error) {
const { isErrorExpected } = parseWalletError({ error, stringGetter });
if (!isErrorExpected) {
throw Object.assign(
new Error([error.message, error.cause?.message].filter(Boolean).join('\n')),
{
walletConnectionType: walletConnection?.type,
}
);
}
throw Object.assign(
new Error([error.message, error.cause?.message].filter(Boolean).join('\n')),
{
walletConnectionType: walletConnection?.type,
}
);
}
return {
walletType,
walletConnectionType: walletConnection?.type,
walletConnectionType: walletConnection.type,
};
},
[isConnectedGraz, signerGraz, isConnectedWagmi, signerWagmi]
+4 -4
View File
@@ -36,8 +36,8 @@ const ChaosLabsIcon: React.FC = () => {
fill={fills[1]}
/>
<path
fillRule="evenodd"
clipRule="evenodd"
fill-rule="evenodd"
clip-rule="evenodd"
d="M47.6624 4.38721C46.5167 4.38721 45.5396 4.77222 44.7521 5.54468C43.9625 6.31199 43.5687 7.27749 43.5687 8.41904C43.5687 9.55454 43.9632 10.5194 44.7514 11.2929L44.7527 11.2939C45.5403 12.0594 46.5173 12.4406 47.6624 12.4406C48.8074 12.4406 49.7845 12.0594 50.572 11.2939L50.5734 11.2929C51.3616 10.5194 51.756 9.55454 51.756 8.41904C51.756 7.27749 51.3623 6.312 50.5727 5.54469C49.7851 4.77223 48.8081 4.38721 47.6624 4.38721ZM45.4207 8.41904C45.4207 7.76676 45.6364 7.22501 46.0671 6.77549C46.5039 6.32689 47.0294 6.10561 47.6624 6.10561C48.2954 6.10561 48.8168 6.32697 49.2462 6.77466L49.2476 6.77617C49.6857 7.22615 49.9034 7.7677 49.9034 8.41904C49.9034 9.06265 49.6864 9.60104 49.2476 10.0516L49.2462 10.0531C48.8168 10.5008 48.2954 10.7222 47.6624 10.7222C47.0294 10.7222 46.5039 10.5009 46.0671 10.0523C45.6357 9.60218 45.4207 9.06359 45.4207 8.41904Z"
fill={fills[1]}
/>
@@ -50,8 +50,8 @@ const ChaosLabsIcon: React.FC = () => {
fill={fills[1]}
/>
<path
fillRule="evenodd"
clipRule="evenodd"
fill-rule="evenodd"
clip-rule="evenodd"
d="M40.3586 4.56055H38.6659L35.2261 12.3667H37.1862L37.9072 10.7289H41.1173L41.8383 12.3667H43.7984L40.3586 4.56055ZM38.6686 9.00014L39.5126 7.08737L40.3559 9.00014H38.6686Z"
fill={fills[1]}
/>
-4
View File
@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.9255 9.70119C10.9255 8.14969 9.99456 7.61773 8.13272 7.39612C6.80283 7.21876 6.53685 6.86416 6.53685 6.24348C6.53685 5.62279 6.98018 5.22393 7.86674 5.22393C8.66467 5.22393 9.10801 5.48991 9.32962 6.15485C9.37398 6.28784 9.50697 6.37647 9.63996 6.37647H10.3492C10.5265 6.37647 10.6595 6.24348 10.6595 6.06623V6.02186C10.4822 5.04658 9.68422 4.29301 8.66467 4.20439V3.14047C8.66467 2.96312 8.53169 2.83013 8.31007 2.78577H7.64513C7.46777 2.78577 7.33479 2.91876 7.29042 3.14047V4.16002C5.96053 4.33737 5.11834 5.22393 5.11834 6.33221C5.11834 7.79508 6.0049 8.3713 7.86674 8.59302C9.10801 8.81463 9.50697 9.08061 9.50697 9.78992C9.50697 10.4992 8.88629 10.9868 8.0441 10.9868C6.89145 10.9868 6.49249 10.4991 6.3595 9.83418C6.31524 9.65693 6.18225 9.5682 6.04926 9.5682H5.29559C5.11834 9.5682 4.98535 9.70119 4.98535 9.87854V9.92291C5.1626 11.0311 5.87191 11.829 7.33479 12.0507V13.1146C7.33479 13.2919 7.46778 13.4249 7.68939 13.4692H8.35433C8.53169 13.4692 8.66468 13.3363 8.70904 13.1146V12.0507C10.0389 11.829 10.9255 10.8981 10.9255 9.70119Z" fill="currentColor"/>
<path d="M5.73821 14.3561C2.2805 13.1149 0.507281 9.25822 1.79291 5.84477C2.45786 3.98293 3.92073 2.56441 5.73821 1.89947C5.91557 1.81085 6.00419 1.67786 6.00419 1.45614V0.835558C6.00419 0.658204 5.91557 0.525216 5.73821 0.480957C5.69385 0.480957 5.60522 0.480957 5.56086 0.525215C1.34958 1.8551 -0.955596 6.33247 0.374292 10.5437C1.17223 13.0262 3.07843 14.9324 5.56086 15.7303C5.73821 15.8189 5.91557 15.7303 5.95982 15.553C6.00419 15.5087 6.00419 15.4643 6.00419 15.3757V14.755C6.00419 14.622 5.8712 14.4448 5.73821 14.3561ZM10.4372 0.525215C10.2598 0.436592 10.0825 0.525216 10.0382 0.70257C9.99385 0.746935 9.99385 0.791193 9.99385 0.879924V1.5005C9.99385 1.67786 10.1268 1.8551 10.2598 1.94383C13.7175 3.18499 15.4908 7.04167 14.2051 10.4551C13.5402 12.317 12.0773 13.7355 10.2598 14.4004C10.0825 14.489 9.99385 14.622 9.99385 14.8438V15.4643C9.99385 15.6417 10.0825 15.7747 10.2598 15.8189C10.3042 15.8189 10.3928 15.8189 10.4372 15.7747C14.6485 14.4448 16.9536 9.96742 15.6238 5.75615C14.8258 3.22936 12.8752 1.32315 10.4372 0.525215Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 13.5V8M10.5 13.5V8M5.5 13.5V8M2 5.5L8 1.5L14 5.5M13 13.5V6.388C11.3459 6.12904 9.67421 5.99931 8 6C6.29933 6 4.62933 6.13333 3 6.388V13.5M2 13.5H14M8 4H8.00533V4.00533H8V4Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 360 B

+1 -3
View File
@@ -1,3 +1,4 @@
import ChaosLabsIcon from './chaos-labs';
export { default as AddressConnectorIcon } from './address-connector.svg';
export { default as ArrowIcon } from './arrow.svg';
export { default as Bar3Icon } from './bar3.svg';
@@ -19,7 +20,6 @@ export { default as CoinMarketCapIcon } from './logos/coinmarketcap.svg';
export { default as CoinsIcon } from './coins.svg';
export { default as CommentIcon } from './comment.svg';
export { default as CopyIcon } from './copy.svg';
export { default as CurrencySignIcon } from './currency-sign.svg';
export { default as DepositIcon } from './deposit.svg';
export { default as DepthChartIcon } from './depth-chart.svg';
export { default as DiscordIcon } from './discord.svg';
@@ -29,7 +29,6 @@ export { default as FileIcon } from './file.svg';
export { default as FundingChartIcon } from './funding-chart.svg';
export { default as GearIcon } from './gear.svg';
export { default as GiftboxIcon } from './giftbox.svg';
export { default as GovernanceIcon } from './governance.svg';
export { default as HelpCircleIcon } from './help-circle.svg';
export { default as HideIcon } from './hide.svg';
export { default as HistoryIcon } from './history.svg';
@@ -61,7 +60,6 @@ export { default as StarIcon } from './star.svg';
export { default as SunIcon } from './sun.svg';
export { default as TerminalIcon } from './terminal.svg';
export { default as TogglesMenuIcon } from './toggles-menu.svg';
export { default as TokenIcon } from './token.svg';
export { default as TradeIcon } from './trade.svg';
export { default as TransferIcon } from './transfer.svg';
export { default as TriangleIcon } from './triangle.svg';
-5
View File
@@ -1,5 +0,0 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.78448 0L0.498535 11.999H3.0425L11.3714 0H8.78448Z" fill="currentColor"/>
<path d="M3.30742 0L5.74539 3.53569L4.47339 5.46426L0.710449 0H3.30742Z" fill="currentColor"/>
<path d="M9.03109 12L6.32812 8.08934L7.73738 6.21436L11.575 12H9.03109Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 378 B

-2
View File
@@ -30,7 +30,6 @@ import { OrderDetailsDialog } from '@/views/dialogs/DetailsDialog/OrderDetailsDi
import { FillDetailsDialog } from '@/views/dialogs/DetailsDialog/FillDetailsDialog';
import { NewMarketMessageDetailsDialog } from '@/views/dialogs/NewMarketMessageDetailsDialog';
import { NewMarketAgreementDialog } from '@/views/dialogs/NewMarketAgreementDialog';
import { ExternalNavStrideDialog } from '@/views/dialogs/ExternalNavStrideDialog';
export const DialogManager = () => {
const dispatch = useDispatch();
@@ -60,7 +59,6 @@ export const DialogManager = () => {
[DialogTypes.Help]: <HelpDialog {...modalProps} />,
[DialogTypes.ExternalNavKeplr]: <ExternalNavKeplrDialog {...modalProps} />,
[DialogTypes.ExternalLink]: <ExternalLinkDialog {...modalProps} />,
[DialogTypes.ExternalNavStride]: <ExternalNavStrideDialog {...modalProps} />,
[DialogTypes.MnemonicExport]: <MnemonicExportDialog {...modalProps} />,
[DialogTypes.MobileSignIn]: <MobileSignInDialog {...modalProps} />,
[DialogTypes.Onboarding]: <OnboardingDialog {...modalProps} />,
+6 -12
View File
@@ -31,7 +31,6 @@ import {
type HumanReadableTransferPayload,
} from '@/constants/abacus';
import { DEFAULT_TRANSACTION_MEMO } from '@/constants/analytics';
import { DialogTypes } from '@/constants/dialogs';
import { UNCOMMITTED_ORDER_TIMEOUT_MS } from '@/constants/trade';
import { ENVIRONMENT_CONFIG_MAP, DydxNetwork, isTestnet } from '@/constants/networks';
@@ -116,8 +115,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
{
broadcastPollIntervalMs: 3_000,
broadcastTimeoutMs: 60_000,
},
DEFAULT_TRANSACTION_MEMO
}
)
)
);
@@ -372,8 +370,8 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
value: {
...params.msg,
timeoutTimestamp: params.msg.timeoutTimestamp
? // Squid returns timeoutTimestamp as Long, but the signer expects BigInt
BigInt(Long.fromValue(params.msg.timeoutTimestamp).toString())
// Squid returns timeoutTimestamp as Long, but the signer expects BigInt
? BigInt(Long.fromValue(params.msg.timeoutTimestamp).toString())
: undefined,
},
};
@@ -389,11 +387,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
}
ibcMsg.value.token.amount = amount.toString();
const tx = await this.nobleClient.send(
[ibcMsg],
undefined,
`${DEFAULT_TRANSACTION_MEMO} | ${this.nobleWallet?.address}`
);
const tx = await this.nobleClient.send([ibcMsg]);
const parsedTx = this.parseToPrimitives(tx);
@@ -432,8 +426,8 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
value: {
...parsedIbcPayload.msg,
timeoutTimestamp: parsedIbcPayload.msg.timeoutTimestamp
? // Squid returns timeoutTimestamp as Long, but the signer expects BigInt
BigInt(Long.fromValue(parsedIbcPayload.msg.timeoutTimestamp).toString())
// Squid returns timeoutTimestamp as Long, but the signer expects BigInt
? BigInt(Long.fromValue(parsedIbcPayload.msg.timeoutTimestamp).toString())
: undefined,
},
};
+4
View File
@@ -19,6 +19,10 @@ class TestFlags {
return !!this.queryParams.displayinitializingmarkets;
}
get showMobileSignInOption() {
return !!this.queryParams.mobilesignin;
}
get addressOverride():string {
return this.queryParams.address;
}
+1 -11
View File
@@ -92,10 +92,6 @@ export const getWalletErrorType = ({ error }: { error: Error }) => {
return WalletErrorType.ChainMismatch;
}
if (messageLower.includes('Missing or invalid. request() method: wallet_switchEthereumChain')) {
return WalletErrorType.SwitchChainMethodMissing;
}
// ImToken - User canceled
if (messageLower.includes('用户取消了操作')) {
return WalletErrorType.UserCanceled;
@@ -117,18 +113,13 @@ export const parseWalletError = ({
}) => {
const walletErrorType = getWalletErrorType({ error });
let message;
let isErrorExpected;
switch (walletErrorType) {
case WalletErrorType.ChainMismatch:
case WalletErrorType.UserCanceled:
case WalletErrorType.SwitchChainMethodMissing: {
isErrorExpected = true;
message = error.message;
case WalletErrorType.UserCanceled: {
break;
}
default: {
isErrorExpected = false;
message = stringGetter({
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
params: {
@@ -141,6 +132,5 @@ export const parseWalletError = ({
return {
walletErrorType,
message,
isErrorExpected,
};
};
+18 -45
View File
@@ -4,15 +4,9 @@ import { useDispatch, useSelector } from 'react-redux';
import { useEnsName } from 'wagmi';
import { useNavigate } from 'react-router-dom';
import { TransferType } from '@/constants/abacus';
import { OnboardingState } from '@/constants/account';
import { ButtonSize } from '@/constants/buttons';
import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS } from '@/constants/localization';
import { AppRoute, PortfolioRoute, HistoryRoute } from '@/constants/routes';
import { wallets } from '@/constants/wallets';
import { useAccounts, useStringGetter, useTokenConfigs } from '@/hooks';
import { breakpoints } from '@/styles';
import { TransferType } from '@/constants/abacus';
import { layoutMixins } from '@/styles/layoutMixins';
import { Details } from '@/components/Details';
@@ -22,6 +16,13 @@ import { IconButton, type IconButtonProps } from '@/components/IconButton';
import { Panel } from '@/components/Panel';
import { Toolbar } from '@/components/Toolbar';
import { OnboardingState } from '@/constants/account';
import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS } from '@/constants/localization';
import { AppRoute, PortfolioRoute, HistoryRoute } from '@/constants/routes';
import { wallets } from '@/constants/wallets';
import { useAccounts, useStringGetter, useTokenConfigs } from '@/hooks';
import {
getHistoricalTradingRewardsForCurrentWeek,
getOnboardingState,
@@ -31,12 +32,10 @@ import { openDialog } from '@/state/dialogs';
import { isTruthy } from '@/lib/isTruthy';
import { truncateAddress } from '@/lib/wallet';
import { DYDXBalancePanel } from './token/rewards/DYDXBalancePanel';
import { MigratePanel } from './token/rewards/MigratePanel';
import { GovernancePanel } from './token/rewards/GovernancePanel';
import { StakingPanel } from './token/staking/StakingPanel';
import { StrideStakingPanel } from './token/staking/StrideStakingPanel';
import { NewMarketsPanel } from './token/rewards/NewMarketsPanel';
import { DYDXBalancePanel } from './rewards/DYDXBalancePanel';
import { MigratePanel } from './rewards/MigratePanel';
import { GovernancePanel } from './rewards/GovernancePanel';
import { StakingPanel } from './rewards/StakingPanel';
const ENS_CHAIN_ID = 1; // Ethereum
@@ -237,9 +236,7 @@ const Profile = () => {
</Styled.HistoryPanel>
<Styled.GovernancePanel />
<Styled.NewMarketsPanel />
<Styled.StakingPanel />
<Styled.StrideStakingPanel />
</Styled.MobileProfileLayout>
);
};
@@ -252,12 +249,11 @@ Styled.MobileProfileLayout = styled.div`
${layoutMixins.contentContainerPage}
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
padding: 1.25rem 0.9rem;
max-width: 100vw;
grid-template-columns: 1fr 1fr;
grid-template-areas:
'header header'
'actions actions'
@@ -266,23 +262,8 @@ Styled.MobileProfileLayout = styled.div`
'balance balance'
'rewards fees'
'history history'
'governance newMarkets'
'keplr stride';
@media ${breakpoints.mobile} {
grid-template-areas:
'header header'
'actions actions'
'settings help'
'migrate migrate'
'balance balance'
'rewards fees'
'history history'
'governance governance'
'newMarkets newMarkets'
'keplr keplr'
'stride stride';
}
'governance governance'
'staking staking';
`;
Styled.Header = styled.header`
@@ -354,7 +335,7 @@ Styled.ActionButton = styled(IconButton)<{ iconName?: IconName }>`
${({ iconName }) =>
iconName === IconName.Close
? css`
--button-textColor: var(--color-red);
--button-textColor: var(--color-error);
--button-icon-size: 0.75em;
`
: iconName === IconName.Transfer &&
@@ -450,13 +431,5 @@ Styled.GovernancePanel = styled(GovernancePanel)`
`;
Styled.StakingPanel = styled(StakingPanel)`
grid-area: keplr;
`;
Styled.NewMarketsPanel = styled(NewMarketsPanel)`
grid-area: newMarkets;
`;
Styled.StrideStakingPanel = styled(StrideStakingPanel)`
grid-area: stride;
grid-area: staking;
`;
+21 -41
View File
@@ -45,8 +45,7 @@ export default () => {
const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {};
const { nativeTokenBalance } = useAccountBalance();
const { numTotalPositions, numTotalOpenOrders } =
useSelector(getTradeInfoNumbers, shallowEqual) || {};
const { numTotalPositions, numTotalOpenOrders } = useSelector(getTradeInfoNumbers, shallowEqual) || {};
const numPositions = shortenNumberForDisplay(numTotalPositions);
const numOrders = shortenNumberForDisplay(numTotalOpenOrders);
@@ -120,43 +119,30 @@ export default () => {
items: [
{
value: PortfolioRoute.Overview,
slotBefore: (
<Styled.IconContainer>
<Icon iconName={IconName.Overview} />
</Styled.IconContainer>
),
slotBefore: <Styled.Icon iconName={IconName.Overview} />,
label: stringGetter({ key: STRING_KEYS.OVERVIEW }),
href: PortfolioRoute.Overview,
},
{
value: PortfolioRoute.Positions,
slotBefore: (
<Styled.IconContainer>
<Icon iconName={IconName.Positions} />
</Styled.IconContainer>
),
slotBefore: <Styled.Icon iconName={IconName.Positions} />,
label: (
<>
{stringGetter({ key: STRING_KEYS.POSITIONS })}
{numPositions &&
(typeof numPositions === 'string' || numPositions > 0) && (
<Tag type={TagType.Number}> {numPositions} </Tag>
)}
{numPositions > 0 && (
<Tag type={TagType.Number}> {numPositions} </Tag>
)}
</>
),
href: PortfolioRoute.Positions,
},
{
value: PortfolioRoute.Orders,
slotBefore: (
<Styled.IconContainer>
<Icon iconName={IconName.OrderPending} />
</Styled.IconContainer>
),
slotBefore: <Styled.Icon iconName={IconName.OrderPending} />,
label: (
<>
{stringGetter({ key: STRING_KEYS.ORDERS })}
{numOrders && (typeof numOrders === 'string' || numOrders > 0) && (
{numOrders > 0 && (
<Tag type={TagType.Number}> {numOrders} </Tag>
)}
</>
@@ -165,21 +151,13 @@ export default () => {
},
{
value: PortfolioRoute.Fees,
slotBefore: (
<Styled.IconContainer>
<Icon iconName={IconName.Calculator} />
</Styled.IconContainer>
),
slotBefore: <Styled.Icon iconName={IconName.Calculator} />,
label: stringGetter({ key: STRING_KEYS.FEES }),
href: PortfolioRoute.Fees,
},
{
value: PortfolioRoute.History,
slotBefore: (
<Styled.IconContainer>
<Icon iconName={IconName.History} />
</Styled.IconContainer>
),
slotBefore: <Styled.Icon iconName={IconName.History} />,
label: stringGetter({ key: STRING_KEYS.HISTORY }),
href: PortfolioRoute.History,
},
@@ -254,14 +232,16 @@ Styled.NavigationMenu = styled(NavigationMenu)`
padding-top: 0;
`;
Styled.IconContainer = styled.div`
width: 1.5rem;
height: 1.5rem;
font-size: 0.75rem;
display: flex;
justify-content: center;
align-items: center;
background-color: var(--color-layer-4);
Styled.Icon = styled(Icon)`
--icon-backgroundColor: var(--color-layer-4);
width: 1em;
height: 1em;
margin-left: -0.25em;
box-sizing: content-box;
background-color: var(--icon-backgroundColor);
border-radius: 50%;
margin-left: -0.25rem;
padding: 0.25em;
`;
@@ -14,14 +14,13 @@ import { Link } from '@/components/Link';
import { openDialog } from '@/state/dialogs';
export const GovernancePanel = ({ className }: { className?: string }) => {
export const GovernancePanel = () => {
const stringGetter = useStringGetter();
const dispatch = useDispatch();
const { governanceLearnMore } = useURLConfigs();
return (
<Panel
className={className}
slotHeaderContent={
<Styled.Title>{stringGetter({ key: STRING_KEYS.GOVERNANCE })}</Styled.Title>
}
@@ -73,4 +72,4 @@ Styled.Title = styled.h3`
font: var(--font-medium-book);
color: var(--color-text-2);
margin-bottom: -1rem;
`;
`;
@@ -28,7 +28,7 @@ import { log } from '@/lib/telemetry';
const SEASON_NUMBER = 2;
export const LaunchIncentivesPanel = ({ className }: { className?: string }) => {
export const LaunchIncentivesPanel = () => {
const { isNotTablet } = useBreakpoints();
const dispatch = useDispatch();
@@ -37,15 +37,11 @@ export const LaunchIncentivesPanel = ({ className }: { className?: string }) =>
}, []);
return isNotTablet ? (
<Styled.Panel
className={className}
slotHeader={<LaunchIncentivesTitle />}
slotRight={<EstimatedRewards />}
>
<Styled.Panel slotHeader={<LaunchIncentivesTitle />} slotRight={<EstimatedRewards />}>
<LaunchIncentivesContent />
</Styled.Panel>
) : (
<Styled.Panel className={className}>
<Styled.Panel>
<Styled.Column>
<EstimatedRewards />
<LaunchIncentivesTitle />
@@ -19,22 +19,21 @@ import { Tag } from '@/components/Tag';
import { MustBigNumber } from '@/lib/numbers';
import { layoutMixins } from '@/styles/layoutMixins';
export const NewMarketsPanel = ({ className }: { className?: string }) => {
export const NewMarketsPanel = () => {
const stringGetter = useStringGetter();
const navigate = useNavigate();
const { hasPotentialMarketsData } = usePotentialMarkets();
const { chainTokenDecimals, chainTokenLabel } = useTokenConfigs();
const { newMarketProposal } = useGovernanceVariables();
const initialDepositAmountDecimals = isMainnet ? 0 : 11;
const initialDepositAmountBN = MustBigNumber(newMarketProposal.initialDepositAmount).div(
Number(`1e${chainTokenDecimals}`)
);
const initialDepositAmountDecimals = isMainnet ? 0 : chainTokenDecimals;
if (!hasPotentialMarketsData) return null;
return (
<Panel
className={className}
slotHeaderContent={
<Styled.Title>
{stringGetter({ key: STRING_KEYS.ADD_A_MARKET })}
@@ -10,8 +10,6 @@ import { breakpoints } from '@/styles';
import { layoutMixins } from '@/styles/layoutMixins';
import { BackButton } from '@/components/BackButton';
import { DetachedSection } from '@/components/ContentSection';
import { ContentSectionHeader } from '@/components/ContentSectionHeader';
import { testFlags } from '@/lib/testFlags';
@@ -21,6 +19,9 @@ import { MigratePanel } from './MigratePanel';
import { RewardsHelpPanel } from './RewardsHelpPanel';
import { TradingRewardsSummaryPanel } from './TradingRewardsSummaryPanel';
import { RewardHistoryPanel } from './RewardHistoryPanel';
import { GovernancePanel } from './GovernancePanel';
import { StakingPanel } from './StakingPanel';
import { NewMarketsPanel } from './NewMarketsPanel';
const RewardsPage = () => {
const stringGetter = useStringGetter();
@@ -28,45 +29,46 @@ const RewardsPage = () => {
const navigate = useNavigate();
return (
<div>
<Styled.Page>
{isTablet && (
<ContentSectionHeader
title={stringGetter({ key: STRING_KEYS.TRADING_REWARDS })}
slotLeft={<BackButton onClick={() => navigate(AppRoute.Profile)} />}
/>
<Styled.MobileHeader>
<BackButton onClick={() => navigate(AppRoute.Profile)} />
{stringGetter({ key: STRING_KEYS.TRADING_REWARDS })}
</Styled.MobileHeader>
)}
<DetachedSection>
<Styled.GridLayout
showTradingRewards={testFlags.showTradingRewards}
showMigratePanel={import.meta.env.VITE_V3_TOKEN_ADDRESS && isNotTablet}
>
{import.meta.env.VITE_V3_TOKEN_ADDRESS && isNotTablet && <Styled.MigratePanel />}
<Styled.GridLayout
showTradingRewards={testFlags.showTradingRewards}
showMigratePanel={import.meta.env.VITE_V3_TOKEN_ADDRESS && isNotTablet}
>
{import.meta.env.VITE_V3_TOKEN_ADDRESS && isNotTablet && <Styled.MigratePanel />}
{isTablet ? (
{isTablet ? (
<Styled.LaunchIncentivesPanel />
) : (
<>
<Styled.LaunchIncentivesPanel />
) : (
<>
<Styled.LaunchIncentivesPanel />
<Styled.DYDXBalancePanel />
</>
)}
<Styled.DYDXBalancePanel />
</>
)}
{testFlags.showTradingRewards && (
<Styled.TradingRewardsColumn>
<TradingRewardsSummaryPanel />
{isTablet && <RewardsHelpPanel />}
<RewardHistoryPanel />
</Styled.TradingRewardsColumn>
)}
{testFlags.showTradingRewards && (
<Styled.TradingRewardsColumn>
<TradingRewardsSummaryPanel />
{isTablet && <RewardsHelpPanel />}
<RewardHistoryPanel />
</Styled.TradingRewardsColumn>
)}
{isNotTablet && (
<Styled.OtherColumn showTradingRewards={testFlags.showTradingRewards}>
<RewardsHelpPanel />
</Styled.OtherColumn>
)}
</Styled.GridLayout>
</DetachedSection>
</div>
{isNotTablet && (
<Styled.OtherColumn showTradingRewards={testFlags.showTradingRewards}>
<NewMarketsPanel />
<GovernancePanel />
<StakingPanel />
<RewardsHelpPanel />
</Styled.OtherColumn>
)}
</Styled.GridLayout>
</Styled.Page>
);
};
@@ -74,6 +76,27 @@ export default RewardsPage;
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Page = styled.div`
${layoutMixins.contentContainerPage}
padding: 2rem;
align-items: center;
> * {
--content-max-width: 80rem;
max-width: min(calc(100vw - 4rem), var(--content-max-width));
}
@media ${breakpoints.tablet} {
--stickyArea-topHeight: var(--page-header-height-mobile);
padding: 0 1rem 1rem;
> * {
max-width: calc(100vw - 2rem);
width: 100%;
}
}
`;
Styled.MobileHeader = styled.header`
${layoutMixins.contentSectionDetachedScrollable}
${layoutMixins.stickyHeader}
@@ -90,7 +113,6 @@ Styled.GridLayout = styled.div<{ showTradingRewards?: boolean; showMigratePanel?
display: grid;
grid-template-columns: 2fr 1fr;
gap: var(--gap);
max-width: 80rem;
> * {
gap: var(--gap);
@@ -101,39 +123,24 @@ Styled.GridLayout = styled.div<{ showTradingRewards?: boolean; showMigratePanel?
? css`
grid-template-areas:
'migrate migrate'
'incentives incentives'
'balance balance'
'incentives balance'
'rewards other';
`
: showTradingRewards
? css`
grid-template-areas:
'incentives balance'
'rewards other';
grid-template-areas: 'incentives balance' 'rewards other';
`
: showMigratePanel
? css`
grid-template-areas:
'migrate migrate'
'incentives incentives'
'balance balance'
'other other';
grid-template-areas: 'migrate migrate' 'incentives balance' 'other other';
`
: css`
grid-template-areas:
'incentives balance'
'other other';
grid-template-areas: 'incentives balance' 'other other';
`};
@media ${breakpoints.notTablet} {
padding: 1rem;
}
@media ${breakpoints.tablet} {
--gap: 1rem;
grid-template-columns: 1fr;
width: calc(100vw - 2rem);
margin: 0 auto;
${({ showTradingRewards }) =>
showTradingRewards
@@ -180,3 +187,13 @@ Styled.OtherColumn = styled.div<{ showTradingRewards?: boolean }>`
}
`}
`;
Styled.RewardHistoryHeader = styled.div`
h3 {
font: var(--font-medium-book);
color: var(--color-text-2);
}
padding: 1rem 1.5rem 0;
margin-bottom: -0.5rem;
`;
@@ -1,6 +1,7 @@
import styled, { AnyStyledComponent } from 'styled-components';
import { useDispatch } from 'react-redux';
import { ButtonAction, ButtonSize } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization';
import { DialogTypes } from '@/constants/dialogs';
@@ -13,19 +14,22 @@ import { Link } from '@/components/Link';
import { openDialog } from '@/state/dialogs';
export const StakingPanel = ({ className }: { className?: string }) => {
export const StakingPanel = () => {
const stringGetter = useStringGetter();
const dispatch = useDispatch();
const { stakingLearnMore } = useURLConfigs();
return (
<Styled.Panel
className={className}
slotHeaderContent={
<Styled.Header>
<Styled.Title>{stringGetter({ key: STRING_KEYS.STAKE_WITH_KEPLR })}</Styled.Title>
<Styled.Img src="/third-party/keplr.png" alt={stringGetter({ key: STRING_KEYS.KEPLR })} />
</Styled.Header>
<Panel
slotHeaderContent={<Styled.Title>{stringGetter({ key: STRING_KEYS.STAKING })}</Styled.Title>}
slotRight={
<Styled.Arrow>
<Styled.IconButton
action={ButtonAction.Base}
iconName={IconName.Arrow}
size={ButtonSize.Small}
/>
</Styled.Arrow>
}
onClick={() => dispatch(openDialog({ type: DialogTypes.ExternalNavKeplr }))}
>
@@ -35,40 +39,12 @@ export const StakingPanel = ({ className }: { className?: string }) => {
{stringGetter({ key: STRING_KEYS.LEARN_MORE })}
</Link>
</Styled.Description>
</Styled.Panel>
</Panel>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Panel = styled(Panel)`
align-items: start;
header {
justify-content: unset;
padding-bottom: 0;
}
`;
Styled.Header = styled.div`
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
`;
Styled.Title = styled.h3`
font: var(--font-medium-book);
color: var(--color-text-2);
`;
Styled.Img = styled.img`
width: 2rem;
height: 2rem;
margin-left: 0.5rem;
`;
Styled.Description = styled.div`
color: var(--color-text-0);
--link-color: var(--color-text-1);
@@ -85,3 +61,13 @@ Styled.IconButton = styled(IconButton)`
color: var(--color-text-0);
--color-border: var(--color-layer-6);
`;
Styled.Arrow = styled.div`
padding-right: 1.5rem;
`;
Styled.Title = styled.h3`
font: var(--font-medium-book);
color: var(--color-text-2);
margin-bottom: -1rem;
`;
@@ -3,8 +3,8 @@ import styled, { AnyStyledComponent } from 'styled-components';
import { shallowEqual, useSelector } from 'react-redux';
import { STRING_KEYS } from '@/constants/localization';
import { useStringGetter, useTokenConfigs } from '@/hooks';
import { layoutMixins } from '@/styles/layoutMixins';
import { useStringGetter, useTokenConfigs } from '@/hooks';
import { AssetIcon } from '@/components/AssetIcon';
import { Details } from '@/components/Details';
@@ -18,10 +18,7 @@ import abacusStateManager from '@/lib/abacus';
export const TradingRewardsSummaryPanel = () => {
const stringGetter = useStringGetter();
const { chainTokenLabel } = useTokenConfigs();
const currentWeekTradingReward = useSelector(
getHistoricalTradingRewardsForCurrentWeek,
shallowEqual
);
const currentWeekTradingReward = useSelector(getHistoricalTradingRewardsForCurrentWeek, shallowEqual);
useEffect(() => {
abacusStateManager.refreshHistoricalTradingRewards();
-60
View File
@@ -1,60 +0,0 @@
import styled, { AnyStyledComponent } from 'styled-components';
import { STRING_KEYS } from '@/constants/localization';
import { useStringGetter } from '@/hooks';
import { breakpoints } from '@/styles';
import { layoutMixins } from '@/styles/layoutMixins';
import { DetachedSection } from '@/components/ContentSection';
import { ContentSectionHeader } from '@/components/ContentSectionHeader';
import { GovernancePanel } from './rewards/GovernancePanel';
import { NewMarketsPanel } from './rewards/NewMarketsPanel';
export default () => {
const stringGetter = useStringGetter();
return (
<DetachedSection>
<Styled.HeaderSection>
<ContentSectionHeader
title={stringGetter({ key: STRING_KEYS.GOVERNANCE })}
subtitle={stringGetter({ key: STRING_KEYS.GOVERNANCE_PAGE_SUBTITLE })}
/>
</Styled.HeaderSection>
<Styled.ContentWrapper>
<Styled.Row>
<GovernancePanel />
<NewMarketsPanel />
</Styled.Row>
</Styled.ContentWrapper>
</DetachedSection>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.HeaderSection = styled.section`
${layoutMixins.contentSectionDetached}
@media ${breakpoints.tablet} {
${layoutMixins.flexColumn}
gap: 1rem;
margin-bottom: 0.5rem;
}
`;
Styled.ContentWrapper = styled.div`
${layoutMixins.flexColumn}
gap: 1.5rem;
max-width: 80rem;
padding: 0 1rem;
`;
Styled.Row = styled.div`
gap: 1rem;
display: grid;
grid-template-columns: repeat(3, 1fr);
`;
-126
View File
@@ -1,126 +0,0 @@
import { Suspense, lazy } from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import styled, { AnyStyledComponent } from 'styled-components';
import { STRING_KEYS } from '@/constants/localization';
import { TokenRoute } from '@/constants/routes';
import { useBreakpoints, useStringGetter } from '@/hooks';
import { layoutMixins } from '@/styles/layoutMixins';
import { Icon, IconName } from '@/components/Icon';
import { LoadingSpace } from '@/components/Loading/LoadingSpinner';
import { NavigationMenu } from '@/components/NavigationMenu';
import { WithSidebar } from '@/components/WithSidebar';
const RewardsPage = lazy(() => import('./rewards/RewardsPage'));
const StakingPage = lazy(() => import('./staking/StakingPage'));
const GovernancePage = lazy(() => import('./Governance'));
export default () => {
const { isTablet } = useBreakpoints();
const stringGetter = useStringGetter();
const routesComponent = (
<Suspense fallback={<LoadingSpace id="token-page" />}>
<Routes>
<Route path={TokenRoute.TradingRewards} element={<RewardsPage />} />
<Route path={TokenRoute.StakingRewards} element={<StakingPage />} />
<Route path={TokenRoute.Governance} element={<GovernancePage />} />
<Route path="*" element={<Navigate to={TokenRoute.TradingRewards} replace />} />
</Routes>
</Suspense>
);
return (
<WithSidebar
sidebar={
isTablet ? null : (
<Styled.SideBar>
<Styled.NavigationMenu
items={[
{
group: 'views',
groupLabel: stringGetter({ key: STRING_KEYS.VIEWS }),
items: [
{
value: TokenRoute.TradingRewards,
slotBefore: (
<Styled.IconContainer>
<Icon iconName={IconName.Token} />
</Styled.IconContainer>
),
label: stringGetter({ key: STRING_KEYS.TRADING_REWARDS }),
href: TokenRoute.TradingRewards,
},
{
value: TokenRoute.StakingRewards,
slotBefore: (
<Styled.IconContainer>
<Icon iconName={IconName.CurrencySign} />
</Styled.IconContainer>
),
label: stringGetter({ key: STRING_KEYS.STAKING_REWARDS }),
href: TokenRoute.StakingRewards,
tag: stringGetter({ key: STRING_KEYS.NEW }),
},
{
value: TokenRoute.Governance,
slotBefore: (
<Styled.IconContainer>
<Icon iconName={IconName.Governance} />
</Styled.IconContainer>
),
label: stringGetter({ key: STRING_KEYS.GOVERNANCE }),
href: TokenRoute.Governance,
},
],
},
]}
/>
</Styled.SideBar>
)
}
>
{routesComponent}
</WithSidebar>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.SideBar = styled.div`
${layoutMixins.flexColumn}
justify-content: space-between;
height: 100%;
`;
Styled.Footer = styled.div`
${layoutMixins.row}
flex-wrap: wrap;
padding: 1rem;
gap: 0.5rem;
> button {
flex-grow: 1;
}
`;
Styled.NavigationMenu = styled(NavigationMenu)`
padding: 0.5rem;
padding-top: 0;
`;
Styled.IconContainer = styled.div`
width: 1.5rem;
height: 1.5rem;
font-size: 0.75rem;
display: flex;
justify-content: center;
align-items: center;
background-color: var(--color-layer-4);
border-radius: 50%;
margin-left: -0.25rem;
`;
-70
View File
@@ -1,70 +0,0 @@
import styled, { AnyStyledComponent } from 'styled-components';
import { breakpoints } from '@/styles';
import { layoutMixins } from '@/styles/layoutMixins';
import { DetachedSection } from '@/components/ContentSection';
import { ContentSectionHeader } from '@/components/ContentSectionHeader';
import { useStringGetter } from '@/hooks';
import { StakingPanel } from './StakingPanel';
import { StrideStakingPanel } from './StrideStakingPanel';
import { DYDXBalancePanel } from '../rewards/DYDXBalancePanel';
import { STRING_KEYS } from '@/constants/localization';
export default () => {
const stringGetter = useStringGetter();
return (
<DetachedSection>
<Styled.HeaderSection>
<ContentSectionHeader
title={stringGetter({ key: STRING_KEYS.STAKING_REWARDS })}
subtitle={stringGetter({ key: STRING_KEYS.STAKING_PAGE_SUBTITLE })}
/>
</Styled.HeaderSection>
<Styled.ContentWrapper>
<Styled.Row>
<Styled.InnerRow>
<StrideStakingPanel />
<StakingPanel />
</Styled.InnerRow>
<DYDXBalancePanel />
</Styled.Row>
</Styled.ContentWrapper>
</DetachedSection>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.HeaderSection = styled.section`
${layoutMixins.contentSectionDetached}
@media ${breakpoints.tablet} {
${layoutMixins.flexColumn}
gap: 1rem;
margin-bottom: 0.5rem;
}
`;
Styled.ContentWrapper = styled.div`
${layoutMixins.flexColumn}
gap: 1.5rem;
max-width: 80rem;
padding: 0 1rem;
`;
Styled.Row = styled.div`
gap: 1rem;
display: grid;
grid-template-columns: 2fr 1fr;
`;
Styled.InnerRow = styled.div`
gap: 1rem;
display: grid;
grid-template-columns: 1fr 1fr;
height: fit-content;
`;
@@ -1,97 +0,0 @@
import styled, { AnyStyledComponent } from 'styled-components';
import { useDispatch } from 'react-redux';
import { STRING_KEYS } from '@/constants/localization';
import { DialogTypes } from '@/constants/dialogs';
import { useStringGetter, useTokenConfigs, useURLConfigs } from '@/hooks';
import { IconButton } from '@/components/IconButton';
import { Link } from '@/components/Link';
import { Panel } from '@/components/Panel';
import { Tag } from '@/components/Tag';
import { openDialog } from '@/state/dialogs';
export const StrideStakingPanel = ({ className }: { className?: string }) => {
const stringGetter = useStringGetter();
const dispatch = useDispatch();
const { stakingLearnMore } = useURLConfigs();
const { chainTokenLabel } = useTokenConfigs();
return (
<Styled.Panel
className={className}
slotHeaderContent={
<Styled.Header>
<Styled.Title>
{stringGetter({ key: STRING_KEYS.LIQUID_STAKE_W_STRIDE })}
<Tag isHighlighted>{stringGetter({ key: STRING_KEYS.NEW })}</Tag>
</Styled.Title>
<Styled.Img src="/third-party/stride.png" alt="Stride" />
</Styled.Header>
}
onClick={() => dispatch(openDialog({ type: DialogTypes.ExternalNavStride }))}
>
<Styled.Description>
{stringGetter({
key: STRING_KEYS.LIQUID_STAKE_STRIDE_DESCRIPTION,
params: { TOKEN_DENOM: chainTokenLabel },
})}
<Link href={stakingLearnMore} onClick={(e) => e.stopPropagation()}>
{stringGetter({ key: STRING_KEYS.LEARN_MORE })}
</Link>
</Styled.Description>
</Styled.Panel>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Panel = styled(Panel)`
align-items: start;
header {
justify-content: unset;
padding-bottom: 0;
}
`;
Styled.Header = styled.div`
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
`;
Styled.Title = styled.h3`
font: var(--font-medium-book);
color: var(--color-text-2);
display: flex;
align-items: center;
gap: 0.5ch;
`;
Styled.Img = styled.img`
width: 2rem;
height: 2rem;
margin-left: 0.5rem;
`;
Styled.Description = styled.div`
color: var(--color-text-0);
--link-color: var(--color-text-1);
a {
display: inline;
::before {
content: ' ';
}
}
`;
Styled.IconButton = styled(IconButton)`
color: var(--color-text-0);
--color-border: var(--color-layer-6);
`;
-4
View File
@@ -2,10 +2,6 @@ import { createGlobalStyle } from 'styled-components';
export const GlobalStyle = createGlobalStyle`
:root {
--color-white: ${({ theme }) => theme.white};
--color-green: ${({ theme }) => theme.green};
--color-red: ${({ theme }) => theme.red};
--color-layer-0: ${({ theme }) => theme.layer0};
--color-layer-1: ${({ theme }) => theme.layer1};
--color-layer-2: ${({ theme }) => theme.layer2};
+3 -12
View File
@@ -4,10 +4,6 @@ import { BrightnessFilterToken, ColorToken, OpacityToken } from '@/constants/sty
import { generateFadedColorVariant } from '@/lib/styles';
const ClassicThemeBase: ThemeColorBase = {
white: ColorToken.White,
green: ColorToken.Green1,
red: ColorToken.Red2,
layer0: ColorToken.GrayBlue7,
layer1: ColorToken.GrayBlue6,
layer2: ColorToken.GrayBlue5,
@@ -55,6 +51,7 @@ const ClassicThemeBase: ThemeColorBase = {
inputBackground: ColorToken.GrayBlue3,
popoverBackground: generateFadedColorVariant(ColorToken.GrayBlue4, OpacityToken.Opacity90),
switchThumbActiveBackground: ColorToken.White,
toggleBackground: ColorToken.GrayBlue3,
tooltipBackground: generateFadedColorVariant(ColorToken.GrayBlue3, OpacityToken.Opacity66),
@@ -64,10 +61,6 @@ const ClassicThemeBase: ThemeColorBase = {
};
const DarkThemeBase: ThemeColorBase = {
white: ColorToken.White,
green: ColorToken.Green0,
red: ColorToken.Red0,
layer0: ColorToken.Black,
layer1: ColorToken.DarkGray11,
layer2: ColorToken.DarkGray13,
@@ -115,6 +108,7 @@ const DarkThemeBase: ThemeColorBase = {
inputBackground: ColorToken.DarkGray6,
popoverBackground: generateFadedColorVariant(ColorToken.DarkGray8, OpacityToken.Opacity90),
switchThumbActiveBackground: ColorToken.White,
toggleBackground: ColorToken.DarkGray6,
tooltipBackground: generateFadedColorVariant(ColorToken.DarkGray6, OpacityToken.Opacity66),
@@ -124,10 +118,6 @@ const DarkThemeBase: ThemeColorBase = {
};
const LightThemeBase: ThemeColorBase = {
white: ColorToken.White,
green: ColorToken.Green2,
red: ColorToken.Red1,
layer0: ColorToken.White,
layer1: ColorToken.LightGray6,
layer2: ColorToken.White,
@@ -175,6 +165,7 @@ const LightThemeBase: ThemeColorBase = {
inputBackground: ColorToken.White,
popoverBackground: generateFadedColorVariant(ColorToken.LightGray8, OpacityToken.Opacity90),
switchThumbActiveBackground: ColorToken.White,
toggleBackground: ColorToken.LightGray4,
tooltipBackground: generateFadedColorVariant(ColorToken.LightGray7, OpacityToken.Opacity66),
@@ -173,7 +173,7 @@ export const AccountInfoConnectedState = () => {
<WithTooltip tooltip={tooltip} stringParams={stringParams}>
<Styled.WithUsage>
{label}
{hasError ? <Styled.CautionIcon iconName={IconName.CautionCircle} /> : slotRight}
{hasError ? <Styled.Icon iconName={IconName.CautionCircle} /> : slotRight}
</Styled.WithUsage>
</WithTooltip>
),
@@ -230,7 +230,7 @@ Styled.CircleContainer = styled.div`
border-radius: 50%;
`;
Styled.CautionIcon = styled(Icon)`
Styled.Icon = styled(Icon)`
color: var(--color-error);
`;
+3 -3
View File
@@ -557,11 +557,11 @@ Styled.PositionTile = styled(PositionTile)``;
Styled.ClosePositionButton = styled(Button)`
--button-border: solid var(--border-width) var(--color-border-red);
--button-textColor: var(--color-red);
--button-textColor: var(--color-error);
`;
Styled.ClosePositionToggleButton = styled(ToggleButton)`
--button-border: solid var(--border-width) var(--color-border-red);
--button-toggle-off-textColor: var(--color-red);
--button-toggle-on-textColor: var(--color-red);
--button-toggle-off-textColor: var(--color-error);
--button-toggle-on-textColor: var(--color-error);
`;
+1 -3
View File
@@ -33,11 +33,9 @@ Styled.PositionInfoContainer = styled.div`
PositionTileStory.args = {
currentSize: 0.2,
notionalTotal: 1300,
oraclePrice: 1300,
postOrderSize: 0.2,
stepSizeDecimals: 3,
symbol: 'ETH',
tickSizeDecimals: 1,
isLoading: false,
showNarrowVariation: false,
};
+3 -2
View File
@@ -39,6 +39,7 @@ export const DisplaySettingsDialog = ({ setIsOpen }: ElementProps) => {
const sectionHeader = (heading: string) => {
return (
<Styled.Header>
{heading}
{heading}
<HorizontalSeparatorFiller />
</Styled.Header>
@@ -286,10 +287,10 @@ Styled.ArrowIcon = styled(Icon)<{ direction: 'up' | 'down'; color: 'green' | 're
${({ color }) =>
({
['green']: css`
color: var(--color-green);
color: var(--color-success);
`,
['red']: css`
color: var(--color-red);
color: var(--color-error);
`,
}[color])}
`;
+3 -15
View File
@@ -1,4 +1,3 @@
import type { ReactNode } from 'react';
import styled, { type AnyStyledComponent } from 'styled-components';
import { ButtonAction, ButtonType } from '@/constants/buttons';
@@ -11,37 +10,26 @@ import { Dialog } from '@/components/Dialog';
import { layoutMixins } from '@/styles/layoutMixins';
type ElementProps = {
buttonText?: ReactNode;
link: string;
linkDescription?: string;
title?: ReactNode;
slotContent?: ReactNode;
setIsOpen: (open: boolean) => void;
};
export const ExternalLinkDialog = ({
setIsOpen,
buttonText,
link,
linkDescription,
title,
slotContent,
}: ElementProps) => {
export const ExternalLinkDialog = ({ setIsOpen, link, linkDescription }: ElementProps) => {
const stringGetter = useStringGetter();
return (
<Dialog
isOpen
setIsOpen={setIsOpen}
title={title ?? stringGetter({ key: STRING_KEYS.LEAVING_WEBSITE })}
title={stringGetter({ key: STRING_KEYS.LEAVING_WEBSITE })}
description={
linkDescription ?? stringGetter({ key: STRING_KEYS.LEAVING_WEBSITE_DESCRIPTION })
}
>
<Styled.Content>
{slotContent}
<p>{stringGetter({ key: STRING_KEYS.LEAVING_WEBSITE_DISCLAIMER })}.</p>
<Button type={ButtonType.Link} action={ButtonAction.Primary} href={link}>
{buttonText ?? stringGetter({ key: STRING_KEYS.CONTINUE })}
{stringGetter({ key: STRING_KEYS.CONTINUE })}
</Button>
</Styled.Content>
</Dialog>
+3 -28
View File
@@ -1,9 +1,6 @@
import { useCallback } from 'react';
import styled, { type AnyStyledComponent } from 'styled-components';
import { useDispatch } from 'react-redux';
import { ButtonAction, ButtonSize, ButtonType } from '@/constants/buttons';
import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS } from '@/constants/localization';
import { useBreakpoints, useStringGetter, useURLConfigs } from '@/hooks';
@@ -12,8 +9,6 @@ import { Dialog, DialogPlacement } from '@/components/Dialog';
import { IconName } from '@/components/Icon';
import { IconButton } from '@/components/IconButton';
import { closeDialog, openDialog } from '@/state/dialogs';
import { layoutMixins } from '@/styles/layoutMixins';
type ElementProps = {
@@ -23,20 +18,8 @@ type ElementProps = {
export const ExternalNavKeplrDialog = ({ setIsOpen }: ElementProps) => {
const stringGetter = useStringGetter();
const { keplrDashboard, accountExportLearnMore } = useURLConfigs();
const dispatch = useDispatch();
const { isTablet } = useBreakpoints();
const onExternalNavDialog = useCallback(() => {
dispatch(closeDialog());
dispatch(
openDialog({
type: DialogTypes.ExternalLink,
dialogProps: {
link: keplrDashboard,
},
})
);
}, [dispatch]);
const { isTablet } = useBreakpoints();
return (
<Dialog
@@ -46,11 +29,7 @@ export const ExternalNavKeplrDialog = ({ setIsOpen }: ElementProps) => {
placement={isTablet ? DialogPlacement.FullScreen : DialogPlacement.Default}
>
<Styled.Content>
<Styled.Button
type={ButtonType.Button}
size={ButtonSize.XLarge}
onClick={onExternalNavDialog}
>
<Styled.Button type={ButtonType.Link} size={ButtonSize.XLarge} href={keplrDashboard}>
<span>
{stringGetter({
key: STRING_KEYS.NAVIGATE_TO_KEPLR,
@@ -67,11 +46,7 @@ export const ExternalNavKeplrDialog = ({ setIsOpen }: ElementProps) => {
/>
</Styled.Button>
<Styled.Button
type={ButtonType.Link}
size={ButtonSize.XLarge}
href={accountExportLearnMore}
>
<Styled.Button type={ButtonType.Link} size={ButtonSize.XLarge} href={accountExportLearnMore}>
<span>
{stringGetter({
key: STRING_KEYS.LEARN_TO_EXPORT,
@@ -1,149 +0,0 @@
import { useCallback } from 'react';
import styled, { type AnyStyledComponent } from 'styled-components';
import { useDispatch } from 'react-redux';
import { ButtonAction, ButtonSize, ButtonType } from '@/constants/buttons';
import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS } from '@/constants/localization';
import { useBreakpoints, useStringGetter, useURLConfigs } from '@/hooks';
import { layoutMixins } from '@/styles/layoutMixins';
import { Button } from '@/components/Button';
import { Dialog, DialogPlacement } from '@/components/Dialog';
import { Icon, IconName } from '@/components/Icon';
import { IconButton } from '@/components/IconButton';
import { closeDialog, openDialog } from '@/state/dialogs';
type ElementProps = {
setIsOpen: (open: boolean) => void;
};
export const ExternalNavStrideDialog = ({ setIsOpen }: ElementProps) => {
const stringGetter = useStringGetter();
const { strideZoneApp, accountExportLearnMore } = useURLConfigs();
const dispatch = useDispatch();
const { isTablet } = useBreakpoints();
const openExternalNavDialog = useCallback(() => {
dispatch(closeDialog());
dispatch(
openDialog({
type: DialogTypes.ExternalLink,
dialogProps: {
buttonText: (
<Styled.Span>
{stringGetter({ key: STRING_KEYS.LIQUID_STAKE_ON_STRIDE })}
<Icon iconName={IconName.LinkOut} />
</Styled.Span>
),
link: strideZoneApp,
title: stringGetter({ key: STRING_KEYS.LIQUID_STAKING_AND_LEAVING }),
slotContent: stringGetter({
key: STRING_KEYS.LIQUID_STAKING_AND_LEAVING_DESCRIPTION,
params: {
CTA: stringGetter({ key: STRING_KEYS.LIQUID_STAKE_ON_STRIDE }),
},
}),
},
})
);
}, [dispatch, stringGetter]);
return (
<Dialog
isOpen
setIsOpen={setIsOpen}
title={stringGetter({ key: STRING_KEYS.HAVE_YOU_EXPORTED })}
placement={isTablet ? DialogPlacement.FullScreen : DialogPlacement.Default}
>
<Styled.Content>
<Styled.Button
type={ButtonType.Button}
size={ButtonSize.XLarge}
onClick={openExternalNavDialog}
>
<span>
{stringGetter({
key: STRING_KEYS.NAVIGATE_TO_STRIDE,
params: {
STRONG_YES: <strong>{stringGetter({ key: STRING_KEYS.YES })}</strong>,
},
})}
</span>
<Styled.IconButton
action={ButtonAction.Base}
iconName={IconName.Arrow}
size={ButtonSize.XSmall}
/>
</Styled.Button>
<Styled.Button
type={ButtonType.Link}
size={ButtonSize.XLarge}
href={accountExportLearnMore}
>
<span>
{stringGetter({
key: STRING_KEYS.LEARN_TO_EXPORT,
params: {
STRONG_NO: <strong>{stringGetter({ key: STRING_KEYS.NO })}</strong>,
},
})}
</span>
<Styled.IconButton
action={ButtonAction.Base}
iconName={IconName.Arrow}
size={ButtonSize.XSmall}
/>
</Styled.Button>
</Styled.Content>
</Dialog>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.TextToggle = styled.div`
${layoutMixins.stickyFooter}
color: var(--color-accent);
cursor: pointer;
margin-top: auto;
&:hover {
text-decoration: underline;
}
`;
Styled.Content = styled.div`
${layoutMixins.stickyArea0}
--stickyArea0-bottomHeight: 2rem;
--stickyArea0-bottomGap: 1rem;
--stickyArea0-totalInsetBottom: 0.5rem;
${layoutMixins.flexColumn}
gap: 1rem;
`;
Styled.Button = styled(Button)`
--button-font: var(--font-base-book);
--button-padding: 0 1.5rem;
gap: 0;
justify-content: space-between;
`;
Styled.IconButton = styled(IconButton)`
color: var(--color-text-0);
--color-border: var(--color-layer-6);
`;
Styled.Span = styled.span`
display: flex;
align-items: center;
gap: 0.5ch;
`;
+2 -1
View File
@@ -155,7 +155,8 @@ Styled.CautionIconContainer = styled.div`
content: '';
width: 2.5rem;
height: 2.5rem;
background-color: var(--color-gradient-error);
background-color: var(--color-error);
opacity: 0.1;
}
`;
@@ -44,6 +44,7 @@ export const GenerateKeys = ({
onKeysDerived = () => {},
}: ElementProps) => {
const stringGetter = useStringGetter();
const { isMobile } = useBreakpoints();
const [shouldRememberMe, setShouldRememberMe] = useState(false);
@@ -65,30 +66,17 @@ export const GenerateKeys = ({
try {
await matchNetwork?.();
return true;
} catch (error) {
const { message, walletErrorType, isErrorExpected } = parseWalletError({
error,
stringGetter,
});
if (!isErrorExpected) {
log('GenerateKeys/switchNetwork', error, { walletErrorType });
}
const { message, walletErrorType } = parseWalletError({ error, stringGetter });
if (message) {
log('GenerateKeys/switchNetwork', error, { walletErrorType });
setError(message);
throw error;
}
return false;
}
};
const switchNetworkAndDeriveKeys = async () => {
const networkSwitched = await switchNetwork();
if (networkSwitched) await deriveKeys();
};
// 2. Derive keys from EVM account
const { getWalletFromEvmSignature } = useDydxClient();
const { getSubaccounts } = useAccounts();
@@ -166,16 +154,11 @@ export const GenerateKeys = ({
setStatus(EvmDerivedAccountStatus.Derived);
} catch (error) {
setStatus(EvmDerivedAccountStatus.NotDerived);
const { message, walletErrorType, isErrorExpected } = parseWalletError({
error,
stringGetter,
});
const { message, walletErrorType } = parseWalletError({ error, stringGetter });
if (message) {
setError(message);
if (!isErrorExpected) {
log('GenerateKeys/deriveKeys', error, { walletErrorType });
}
log('GenerateKeys/deriveKeys', error, { walletErrorType });
}
}
};
@@ -248,7 +231,7 @@ export const GenerateKeys = ({
{!isMatchingNetwork ? (
<Button
action={ButtonAction.Primary}
onClick={() => switchNetworkAndDeriveKeys().then(onKeysDerived)}
onClick={() => switchNetwork().then(deriveKeys).then(onKeysDerived)}
state={{ isLoading: isSwitchingNetwork }}
>
{stringGetter({ key: STRING_KEYS.SWITCH_NETWORK })}
@@ -340,7 +323,7 @@ Styled.ReceiptArea = styled.div`
`;
Styled.Green = styled.span`
color: var(--color-green);
color: var(--color-success);
`;
Styled.GreenCheckCircle = styled(GreenCheckCircle)`
@@ -11,7 +11,7 @@ import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS } from '@/constants/localization';
import { isMainnet } from '@/constants/networks';
import { NumberSign, TOKEN_DECIMALS } from '@/constants/numbers';
import type { PotentialMarketItem } from '@/constants/potentialMarkets';
import { LIQUIDITY_TIERS, type PotentialMarketItem } from '@/constants/potentialMarkets';
import {
useAccountBalance,
@@ -19,7 +19,6 @@ import {
useStringGetter,
useSubaccount,
useTokenConfigs,
useURLConfigs,
} from '@/hooks';
import { usePotentialMarkets } from '@/hooks/usePotentialMarkets';
@@ -32,7 +31,6 @@ import { DiffOutput } from '@/components/DiffOutput';
import { FormInput } from '@/components/FormInput';
import { Icon, IconName } from '@/components/Icon';
import { InputType } from '@/components/Input';
import { Link } from '@/components/Link';
import { Output, OutputType } from '@/components/Output';
import { Tag } from '@/components/Tag';
import { WithDetailsReceipt } from '@/components/WithDetailsReceipt';
@@ -64,10 +62,9 @@ export const NewMarketPreviewStep = ({
const stringGetter = useStringGetter();
const { chainTokenDecimals, chainTokenLabel } = useTokenConfigs();
const [errorMessage, setErrorMessage] = useState();
const { exchangeConfigs, liquidityTiers } = usePotentialMarkets();
const { exchangeConfigs } = usePotentialMarkets();
const { submitNewMarketProposal } = useSubaccount();
const { newMarketProposal } = useGovernanceVariables();
const { newMarketProposalLearnMore } = useURLConfigs();
const initialDepositAmountBN = MustBigNumber(newMarketProposal.initialDepositAmount).div(
Number(`1e${chainTokenDecimals}`)
);
@@ -76,7 +73,7 @@ export const NewMarketPreviewStep = ({
const [hasAcceptedTerms, setHasAcceptedTerms] = useState(false);
const { label, initialMarginFraction, maintenanceMarginFraction, impactNotional } =
liquidityTiers[liquidityTier as unknown as keyof typeof liquidityTiers];
LIQUIDITY_TIERS[liquidityTier as unknown as keyof typeof LIQUIDITY_TIERS];
const ticker = `${assetData.baseAsset}-USD`;
@@ -314,15 +311,10 @@ export const NewMarketPreviewStep = ({
</Styled.ButtonRow>
<Styled.Disclaimer>
{stringGetter({
key: STRING_KEYS.PROPOSAL_DISCLAIMER_1,
key: STRING_KEYS.PROPOSAL_DISCLAIMER,
params: {
NUM_TOKENS_REQUIRED: initialDepositAmount,
NATIVE_TOKEN_DENOM: chainTokenLabel,
HERE: (
<Styled.Link href={newMarketProposalLearnMore}>
{stringGetter({ key: STRING_KEYS.HERE })}
</Styled.Link>
),
},
})}
</Styled.Disclaimer>
@@ -402,8 +394,3 @@ Styled.ButtonRow = styled.div`
Styled.Button = styled(Button)`
--button-padding: 0;
`;
Styled.Link = styled(Link)`
--link-color: var(--color-accent);
display: inline;
`;
@@ -12,6 +12,7 @@ import { isMainnet } from '@/constants/networks';
import { TOKEN_DECIMALS } from '@/constants/numbers';
import {
LIQUIDITY_TIERS,
NUM_ORACLES_TO_QUALIFY_AS_SAFE,
type PotentialMarketItem,
} from '@/constants/potentialMarkets';
@@ -73,7 +74,7 @@ export const NewMarketSelectionStep = ({
const { isMobile } = useBreakpoints();
const marketIds = useSelector(getMarketIds, shallowEqual);
const { chainTokenDecimals, chainTokenLabel } = useTokenConfigs();
const { potentialMarkets, exchangeConfigs, liquidityTiers } = usePotentialMarkets();
const { potentialMarkets, exchangeConfigs } = usePotentialMarkets();
const stringGetter = useStringGetter();
const { newMarketProposal } = useGovernanceVariables();
const initialDepositAmountBN = MustBigNumber(newMarketProposal.initialDepositAmount).div(
@@ -165,7 +166,7 @@ export const NewMarketSelectionStep = ({
{assetToAdd?.assetName ?? assetToAdd.baseAsset} <Tag>{assetToAdd?.baseAsset}-USD</Tag>
</Styled.SelectedAsset>
) : (
`${stringGetter({ key: STRING_KEYS.EG })} "BTC-USD"`
'e.g. "BTC-USD"'
)}
</SearchSelectMenu>
{assetToAdd && (
@@ -209,9 +210,9 @@ export const NewMarketSelectionStep = ({
</Styled.ButtonRow>
</Styled.Header>
{Object.keys(liquidityTiers).map((tier) => {
{Object.keys(LIQUIDITY_TIERS).map((tier) => {
const { maintenanceMarginFraction, impactNotional, label, initialMarginFraction } =
liquidityTiers[tier as unknown as keyof typeof liquidityTiers];
LIQUIDITY_TIERS[tier as unknown as keyof typeof LIQUIDITY_TIERS];
return (
<Styled.LiquidityTierRadioButton
key={tier}
@@ -233,7 +234,7 @@ export const NewMarketSelectionStep = ({
items={[
{
key: 'imf',
label: stringGetter({ key: STRING_KEYS.INITIAL_MARGIN_FRACTION_SHORT }),
label: 'IMF',
tooltip: 'initial-margin-fraction',
value: (
<Output
@@ -245,9 +246,7 @@ export const NewMarketSelectionStep = ({
},
{
key: 'mmf',
label: stringGetter({
key: STRING_KEYS.MAINTENANCE_MARGIN_FRACTION_SHORT,
}),
label: 'MMF',
tooltip: 'maintenance-margin-fraction',
value: (
<Output
+4 -4
View File
@@ -306,7 +306,7 @@ export const TransferForm = ({
label={
<Styled.DestinationInputLabel>
{stringGetter({ key: STRING_KEYS.DESTINATION })}
{isAddressValid && <Styled.CheckIcon iconName={IconName.Check} />}
{isAddressValid && <Icon iconName={IconName.Check} />}
</Styled.DestinationInputLabel>
}
type={InputType.Text}
@@ -439,10 +439,10 @@ Styled.InlineRow = styled.span`
Styled.DestinationInputLabel = styled.span`
${layoutMixins.inlineRow}
`;
Styled.CheckIcon = styled(Icon)`
color: var(--color-success);
svg {
color: var(--color-success);
}
`;
Styled.AddressValidationAlertMessage = styled(AlertMessage)`
+7 -5
View File
@@ -1,4 +1,4 @@
import { ElementType, memo } from 'react';
import { memo } from 'react';
import styled, { AnyStyledComponent, css } from 'styled-components';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import type { Dispatch } from '@reduxjs/toolkit';
@@ -7,6 +7,7 @@ import { OnboardingState } from '@/constants/account';
import { ButtonAction, ButtonShape, ButtonSize, ButtonType } from '@/constants/buttons';
import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS, StringGetterFunction, TOOLTIP_STRING_KEYS } from '@/constants/localization';
import { isMainnet } from '@/constants/networks';
import { DydxChainAsset, wallets } from '@/constants/wallets';
import { layoutMixins } from '@/styles/layoutMixins';
@@ -40,6 +41,7 @@ import { getAppTheme } from '@/state/configsSelectors';
import { isTruthy } from '@/lib/isTruthy';
import { truncateAddress } from '@/lib/wallet';
import { MustBigNumber } from '@/lib/numbers';
import { testFlags } from '@/lib/testFlags';
export const AccountMenu = () => {
const stringGetter = useStringGetter();
@@ -106,7 +108,7 @@ export const AccountMenu = () => {
{walletType && (
<Styled.SourceIcon>
<Styled.ConnectorIcon iconName={IconName.AddressConnector} />
<Icon iconComponent={wallets[walletType].icon as ElementType} />
<Icon iconComponent={wallets[walletType].icon} />
</Styled.SourceIcon>
)}
<Styled.Column>
@@ -191,7 +193,7 @@ export const AccountMenu = () => {
},
...(onboardingState === OnboardingState.AccountConnected && hdKey
? [
{
(!isMainnet || testFlags.showMobileSignInOption) && {
value: 'MobileQrSignIn',
icon: <Icon iconName={IconName.Qr} />,
label: stringGetter({ key: STRING_KEYS.TITLE_SIGN_INTO_MOBILE }),
@@ -204,7 +206,7 @@ export const AccountMenu = () => {
highlightColor: 'destroy',
onSelect: () => dispatch(openDialog({ type: DialogTypes.MnemonicExport })),
},
]
].filter(isTruthy)
: []),
{
value: 'Disconnect',
@@ -220,7 +222,7 @@ export const AccountMenu = () => {
{onboardingState === OnboardingState.WalletConnected ? (
<Styled.WarningIcon iconName={IconName.Warning} />
) : onboardingState === OnboardingState.AccountConnected ? (
walletType && <Icon iconComponent={wallets[walletType].icon as ElementType} />
walletType && <Icon iconComponent={wallets[walletType].icon} />
) : null}
{!isTablet && <Styled.Address>{truncateAddress(dydxAddress)}</Styled.Address>}
</Styled.DropdownMenu>
@@ -82,6 +82,6 @@ Styled.ActionButton = styled(IconButton)`
Styled.CancelButton = styled(Styled.ActionButton)`
&:not(:disabled) {
--button-textColor: var(--color-red);
--button-textColor: var(--color-error);
}
`;