Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a3e0ac618 | ||
|
|
707db7b111 | ||
|
|
8c759997d1 |
@@ -13,9 +13,3 @@ BUGSNAG_API_KEY=
|
|||||||
IOS_APP_ID=
|
IOS_APP_ID=
|
||||||
INTERCOM_APP_ID=
|
INTERCOM_APP_ID=
|
||||||
STATUS_PAGE_SCRIPT_URI=
|
STATUS_PAGE_SCRIPT_URI=
|
||||||
|
|
||||||
SMARTBANNER_APP_NAME=
|
|
||||||
SMARTBANNER_ORG_NAME=
|
|
||||||
SMARTBANNER_ICON_URL=
|
|
||||||
SMARTBANNER_APPSTORE_URL=
|
|
||||||
SMARTBANNER_GOOGLEPLAY_URL=
|
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ jobs:
|
|||||||
pnpm run build:inject-amplitude
|
pnpm run build:inject-amplitude
|
||||||
pnpm run build:inject-bugsnag
|
pnpm run build:inject-bugsnag
|
||||||
pnpm run build:inject-statuspage
|
pnpm run build:inject-statuspage
|
||||||
pnpm run build:inject-smartbanner
|
|
||||||
sh scripts/inject-app-deeplinks.sh
|
sh scripts/inject-app-deeplinks.sh
|
||||||
|
|
||||||
- name: Upload to IPFS via web3.storage
|
- name: Upload to IPFS via web3.storage
|
||||||
|
|||||||
+8
-53
@@ -2,25 +2,15 @@ import '@/polyfills';
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import styled from 'styled-components';
|
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 { store } from '@/state/_store';
|
||||||
|
|
||||||
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 { GlobalStyle } from '@/styles/globalStyle';
|
import { GlobalStyle } from '@/styles/globalStyle';
|
||||||
|
|
||||||
import { SelectMenu, SelectItem } from '@/components/SelectMenu';
|
import { SelectMenu, SelectItem } from '@/components/SelectMenu';
|
||||||
|
|
||||||
|
import { AppThemeAndColorModeProvider } from '@/hooks/useAppThemeAndColorMode';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AppTheme,
|
AppTheme,
|
||||||
AppThemeSystemSetting,
|
AppThemeSystemSetting,
|
||||||
@@ -28,38 +18,11 @@ import {
|
|||||||
setAppThemeSetting,
|
setAppThemeSetting,
|
||||||
setAppColorMode,
|
setAppColorMode,
|
||||||
} from '@/state/configs';
|
} from '@/state/configs';
|
||||||
|
import { setLocaleLoaded } from '@/state/localization';
|
||||||
import { setLocaleLoaded, setSelectedLocale } from '@/state/localization';
|
|
||||||
import { store } from '@/state/_store';
|
|
||||||
|
|
||||||
import { config } from '@/lib/wagmi';
|
|
||||||
|
|
||||||
import '@/index.css';
|
import '@/index.css';
|
||||||
import './ladle.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 }) => {
|
export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||||
const [theme, setTheme] = useState(AppTheme.Classic);
|
const [theme, setTheme] = useState(AppTheme.Classic);
|
||||||
const [colorMode, setColorMode] = useState(AppColorMode.GreenUp);
|
const [colorMode, setColorMode] = useState(AppColorMode.GreenUp);
|
||||||
@@ -70,20 +33,9 @@ export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
}, [theme, colorMode]);
|
}, [theme, colorMode]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
store.dispatch(setSelectedLocale({ locale: SupportedLocales.EN }));
|
|
||||||
store.dispatch(setLocaleLoaded(true));
|
store.dispatch(setLocaleLoaded(true));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const content = [...providers].reverse().reduce(
|
|
||||||
(children, Provider) => {
|
|
||||||
return <Provider>{children}</Provider>;
|
|
||||||
},
|
|
||||||
<StoryContent>
|
|
||||||
<GlobalStyle />
|
|
||||||
{children}
|
|
||||||
</StoryContent>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<StoryHeader>
|
<StoryHeader>
|
||||||
@@ -127,7 +79,10 @@ export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
</SelectMenu>
|
</SelectMenu>
|
||||||
</StoryHeader>
|
</StoryHeader>
|
||||||
<hr />
|
<hr />
|
||||||
{content}
|
<AppThemeAndColorModeProvider>
|
||||||
|
<GlobalStyle />
|
||||||
|
<StoryContent>{children}</StoryContent>
|
||||||
|
</AppThemeAndColorModeProvider>
|
||||||
</Provider>
|
</Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ Set environment variables via `.env`.
|
|||||||
- `IOS_APP_ID` (optional): iOS app ID used for enabling deep linking to the iOS app; used with `pnpm run build:inject-app-deeplinks`.
|
- `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`.
|
- `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`.
|
- `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
|
# Deployments
|
||||||
|
|
||||||
@@ -107,9 +107,6 @@ pnpm run build --mode testnet
|
|||||||
If you wish to incorporate analytics via Amplitude and Bugsnag, you can use our scripts:
|
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.
|
`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).
|
For more details, check out Vercel's [official documentation](https://vercel.com/docs).
|
||||||
|
|
||||||
## Deploying to IPFS
|
## Deploying to IPFS
|
||||||
|
|||||||
+2
-3
@@ -15,7 +15,6 @@
|
|||||||
"build:inject-bugsnag": "node scripts/inject-bugsnag.js",
|
"build:inject-bugsnag": "node scripts/inject-bugsnag.js",
|
||||||
"build:inject-intercom": "node scripts/inject-intercom.js",
|
"build:inject-intercom": "node scripts/inject-intercom.js",
|
||||||
"build:inject-statuspage": "node scripts/inject-statuspage.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:ipfs": "node scripts/upload-ipfs.js --verbose",
|
||||||
"deploy:update-ipns": "node scripts/update-ipns.js",
|
"deploy:update-ipns": "node scripts/update-ipns.js",
|
||||||
"deploy:update-dnslink": "node scripts/update-dnslink.js",
|
"deploy:update-dnslink": "node scripts/update-dnslink.js",
|
||||||
@@ -42,7 +41,7 @@
|
|||||||
"@cosmjs/tendermint-rpc": "^0.32.1",
|
"@cosmjs/tendermint-rpc": "^0.32.1",
|
||||||
"@dydxprotocol/v4-abacus": "^1.4.2",
|
"@dydxprotocol/v4-abacus": "^1.4.2",
|
||||||
"@dydxprotocol/v4-client-js": "^1.0.20",
|
"@dydxprotocol/v4-client-js": "^1.0.20",
|
||||||
"@dydxprotocol/v4-localization": "^1.1.25",
|
"@dydxprotocol/v4-localization": "^1.1.22",
|
||||||
"@ethersproject/providers": "^5.7.2",
|
"@ethersproject/providers": "^5.7.2",
|
||||||
"@js-joda/core": "^5.5.3",
|
"@js-joda/core": "^5.5.3",
|
||||||
"@radix-ui/react-accordion": "^1.1.2",
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
@@ -118,7 +117,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.22.5",
|
"@babel/core": "^7.22.5",
|
||||||
"@ladle/react": "^4.0.2",
|
"@ladle/react": "^2.15.0",
|
||||||
"@types/color": "^3.0.3",
|
"@types/color": "^3.0.3",
|
||||||
"@types/crypto-js": "^4.1.1",
|
"@types/crypto-js": "^4.1.1",
|
||||||
"@types/luxon": "^3.3.0",
|
"@types/luxon": "^3.3.0",
|
||||||
|
|||||||
Generated
+712
-1849
File diff suppressed because it is too large
Load Diff
+1291
-1302
File diff suppressed because it is too large
Load Diff
@@ -176,13 +176,6 @@
|
|||||||
"whitepaperLink": "https://dfinity.org/whitepaper.pdf",
|
"whitepaperLink": "https://dfinity.org/whitepaper.pdf",
|
||||||
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/internet-computer/"
|
"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": {
|
"LDO-USD": {
|
||||||
"name": "Lido DAO",
|
"name": "Lido DAO",
|
||||||
"tags": ["Defi"],
|
"tags": ["Defi"],
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
@@ -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 -->
|
|
||||||
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB |
@@ -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`
|
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.
|
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`
|
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`
|
|
||||||
|
|||||||
@@ -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
@@ -52,9 +52,9 @@ const AlertsPage = lazy(() => import('@/pages/AlertsPage'));
|
|||||||
const ProfilePage = lazy(() => import('@/pages/Profile'));
|
const ProfilePage = lazy(() => import('@/pages/Profile'));
|
||||||
const SettingsPage = lazy(() => import('@/pages/settings/Settings'));
|
const SettingsPage = lazy(() => import('@/pages/settings/Settings'));
|
||||||
const TradePage = lazy(() => import('@/pages/trade/Trade'));
|
const TradePage = lazy(() => import('@/pages/trade/Trade'));
|
||||||
|
const RewardsPage = lazy(() => import('@/pages/rewards/RewardsPage'));
|
||||||
const TermsOfUsePage = lazy(() => import('@/pages/TermsOfUsePage'));
|
const TermsOfUsePage = lazy(() => import('@/pages/TermsOfUsePage'));
|
||||||
const PrivacyPolicyPage = lazy(() => import('@/pages/PrivacyPolicyPage'));
|
const PrivacyPolicyPage = lazy(() => import('@/pages/PrivacyPolicyPage'));
|
||||||
const TokenPage = lazy(() => import('@/pages/token/Token'));
|
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ const Content = () => {
|
|||||||
<Route path={MarketsRoute.New} element={<NewMarket />} />
|
<Route path={MarketsRoute.New} element={<NewMarket />} />
|
||||||
<Route path={AppRoute.Markets} element={<MarketsPage />} />
|
<Route path={AppRoute.Markets} element={<MarketsPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path={`/${chainTokenLabel}/*`} element={<TokenPage />} />
|
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
|
||||||
{isTablet && (
|
{isTablet && (
|
||||||
<>
|
<>
|
||||||
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
||||||
@@ -207,7 +207,6 @@ Styled.Content = styled.div<{ isShowingHeader: boolean; isShowingFooter: boolean
|
|||||||
|
|
||||||
Styled.Main = styled.main`
|
Styled.Main = styled.main`
|
||||||
${layoutMixins.contentSectionAttached}
|
${layoutMixins.contentSectionAttached}
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
grid-area: Main;
|
grid-area: Main;
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ const AlertContainer = styled.div<StyleProps>`
|
|||||||
case AlertType.Info: {
|
case AlertType.Info: {
|
||||||
return css`
|
return css`
|
||||||
--alert-accent-color: var(--color-text-1);
|
--alert-accent-color: var(--color-text-1);
|
||||||
|
|
||||||
|
--alert-default-background-opacity: 0.133; // Relative
|
||||||
|
// --alert-background: var(--color-layer-6); // Absolute
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
case AlertType.Success: {
|
case AlertType.Success: {
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ const assetIcons = {
|
|||||||
ETH: '/currencies/eth.png',
|
ETH: '/currencies/eth.png',
|
||||||
FIL: '/currencies/fil.png',
|
FIL: '/currencies/fil.png',
|
||||||
ICP: '/currencies/icp.png',
|
ICP: '/currencies/icp.png',
|
||||||
JUP: '/currencies/jup.png',
|
|
||||||
LDO: '/currencies/ldo.png',
|
LDO: '/currencies/ldo.png',
|
||||||
LINK: '/currencies/link.png',
|
LINK: '/currencies/link.png',
|
||||||
LTC: '/currencies/ltc.png',
|
LTC: '/currencies/ltc.png',
|
||||||
|
|||||||
@@ -103,14 +103,14 @@ const buttonActionVariants = {
|
|||||||
|
|
||||||
[ButtonAction.Create]: css`
|
[ButtonAction.Create]: css`
|
||||||
--button-textColor: var(--color-text-button);
|
--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-border: solid var(--border-width) var(--color-border-white);
|
||||||
--button-hover-filter: brightness(var(--hover-filter-variant));
|
--button-hover-filter: brightness(var(--hover-filter-variant));
|
||||||
`,
|
`,
|
||||||
|
|
||||||
[ButtonAction.Destroy]: css`
|
[ButtonAction.Destroy]: css`
|
||||||
--button-textColor: var(--color-text-button);
|
--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-border: solid var(--border-width) var(--color-border-white);
|
||||||
--button-hover-filter: brightness(var(--hover-filter-variant));
|
--button-hover-filter: brightness(var(--hover-filter-variant));
|
||||||
`,
|
`,
|
||||||
@@ -122,7 +122,7 @@ const buttonActionVariants = {
|
|||||||
`,
|
`,
|
||||||
|
|
||||||
[ButtonAction.Reset]: css`
|
[ButtonAction.Reset]: css`
|
||||||
--button-textColor: var(--color-red);
|
--button-textColor: var(--color-error);
|
||||||
--button-backgroundColor: var(--color-layer-3);
|
--button-backgroundColor: var(--color-layer-3);
|
||||||
--button-border: solid var(--border-width) var(--color-border-red);
|
--button-border: solid var(--border-width) var(--color-border-red);
|
||||||
--button-hover-filter: brightness(var(--hover-filter-variant));
|
--button-hover-filter: brightness(var(--hover-filter-variant));
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { layoutMixins } from '@/styles/layoutMixins';
|
|||||||
type ElementProps = {
|
type ElementProps = {
|
||||||
title: string;
|
title: string;
|
||||||
subtitle?: React.ReactNode;
|
subtitle?: React.ReactNode;
|
||||||
slotLeft?: React.ReactNode;
|
|
||||||
slotRight?: React.ReactNode;
|
slotRight?: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -17,16 +16,14 @@ type StyleProps = {
|
|||||||
export const ContentSectionHeader = ({
|
export const ContentSectionHeader = ({
|
||||||
title,
|
title,
|
||||||
subtitle,
|
subtitle,
|
||||||
slotLeft,
|
|
||||||
slotRight,
|
slotRight,
|
||||||
className,
|
className,
|
||||||
}: ElementProps & StyleProps) => (
|
}: ElementProps & StyleProps) => (
|
||||||
<Styled.ContentSectionHeader className={className}>
|
<Styled.ContentSectionHeader className={className}>
|
||||||
{slotLeft}
|
<div>
|
||||||
<Styled.Header>
|
|
||||||
{title && <h3>{title}</h3>}
|
{title && <h3>{title}</h3>}
|
||||||
{subtitle && <p>{subtitle}</p>}
|
{subtitle && <p>{subtitle}</p>}
|
||||||
</Styled.Header>
|
</div>
|
||||||
{slotRight}
|
{slotRight}
|
||||||
</Styled.ContentSectionHeader>
|
</Styled.ContentSectionHeader>
|
||||||
);
|
);
|
||||||
@@ -43,15 +40,9 @@ Styled.ContentSectionHeader = styled.header<StyleProps>`
|
|||||||
|
|
||||||
padding: 1rem var(--header-horizontal-padding);
|
padding: 1rem var(--header-horizontal-padding);
|
||||||
|
|
||||||
@media ${breakpoints.tablet} {
|
> div {
|
||||||
flex-wrap: wrap;
|
${layoutMixins.column}
|
||||||
--header-horizontal-padding: 1.25rem;
|
|
||||||
}
|
}
|
||||||
`;
|
|
||||||
|
|
||||||
Styled.Header = styled.div`
|
|
||||||
${layoutMixins.column}
|
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
color: var(--color-text-2);
|
color: var(--color-text-2);
|
||||||
@@ -63,4 +54,9 @@ Styled.Header = styled.div`
|
|||||||
font: var(--font-small-book);
|
font: var(--font-small-book);
|
||||||
margin-top: 0.25rem;
|
margin-top: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media ${breakpoints.tablet} {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
--header-horizontal-padding: 1.25rem;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -7,50 +7,35 @@ import { StoryWrapper } from '.ladle/components';
|
|||||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
export const DetailsStory: Story<Parameters<typeof Details>[0]> = (args) => (
|
export const DetailsStory: Story<Parameters<typeof Details>> = () => (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<Styled.Resizable>
|
<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>
|
</Styled.Resizable>
|
||||||
</StoryWrapper>
|
</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> = {};
|
const Styled: Record<string, AnyStyledComponent> = {};
|
||||||
|
|
||||||
Styled.Resizable = styled.section`
|
Styled.Resizable = styled.section`
|
||||||
|
|||||||
@@ -4,18 +4,8 @@ import { DropdownMenu } from '@/components/DropdownMenu';
|
|||||||
|
|
||||||
import { StoryWrapper } from '.ladle/components';
|
import { StoryWrapper } from '.ladle/components';
|
||||||
|
|
||||||
export const DropdownMenuStory: Story<Parameters<typeof DropdownMenu>[0]> = (args) => {
|
export const DropdownMenuStory: Story<Parameters<typeof DropdownMenu>> = (args) => {
|
||||||
return (
|
const exampleItems = [
|
||||||
<StoryWrapper>
|
|
||||||
<DropdownMenu {...args}>
|
|
||||||
<span>Menu</span>
|
|
||||||
</DropdownMenu>
|
|
||||||
</StoryWrapper>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
DropdownMenuStory.args = {
|
|
||||||
items: [
|
|
||||||
{
|
{
|
||||||
value: '0',
|
value: '0',
|
||||||
label: 'Item 0',
|
label: 'Item 0',
|
||||||
@@ -39,9 +29,19 @@ DropdownMenuStory.args = {
|
|||||||
onSelect: () => alert('Item 3 action'),
|
onSelect: () => alert('Item 3 action'),
|
||||||
highlightColor: 'destroy',
|
highlightColor: 'destroy',
|
||||||
},
|
},
|
||||||
],
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StoryWrapper>
|
||||||
|
<DropdownMenu {...args} items={exampleItems}>
|
||||||
|
<span>Menu</span>
|
||||||
|
</DropdownMenu>
|
||||||
|
</StoryWrapper>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DropdownMenuStory.args = {};
|
||||||
|
|
||||||
DropdownMenuStory.argTypes = {
|
DropdownMenuStory.argTypes = {
|
||||||
align: {
|
align: {
|
||||||
options: ['start', 'center', 'end'],
|
options: ['start', 'center', 'end'],
|
||||||
|
|||||||
@@ -91,10 +91,10 @@ Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'create' | 'destroy' }>
|
|||||||
--item-highlighted-textColor: var(--color-accent);
|
--item-highlighted-textColor: var(--color-accent);
|
||||||
`,
|
`,
|
||||||
['create']: `
|
['create']: `
|
||||||
--item-highlighted-textColor: var(--color-green);
|
--item-highlighted-textColor: var(--color-success);
|
||||||
`,
|
`,
|
||||||
['destroy']: `
|
['destroy']: `
|
||||||
--item-highlighted-textColor: var(--color-red);
|
--item-highlighted-textColor: var(--color-error);
|
||||||
`,
|
`,
|
||||||
}[$highlightColor])}
|
}[$highlightColor])}
|
||||||
|
|
||||||
|
|||||||
@@ -28,22 +28,21 @@ const exampleItems = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const DropdownSelectMenuStory: Story<
|
export const DropdownSelectMenuStory: Story<Parameters<typeof DropdownSelectMenu>> = (args) => {
|
||||||
Pick<Parameters<typeof DropdownSelectMenu>[0], 'items' | 'align' | 'sideOffset' | 'disabled'>
|
|
||||||
> = (args) => {
|
|
||||||
const [item, setItem] = useState(exampleItems[0].value);
|
const [item, setItem] = useState(exampleItems[0].value);
|
||||||
return (
|
return (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<DropdownSelectMenu value={item} onValueChange={(value) => setItem(value)} {...args} />
|
<DropdownSelectMenu
|
||||||
|
items={exampleItems}
|
||||||
|
value={item}
|
||||||
|
onValueChange={(value) => setItem(value)}
|
||||||
|
{...args}
|
||||||
|
/>
|
||||||
</StoryWrapper>
|
</StoryWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
DropdownSelectMenuStory.args = {
|
DropdownSelectMenuStory.args = {};
|
||||||
items: exampleItems,
|
|
||||||
sideOffset: 1,
|
|
||||||
disabled: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
DropdownSelectMenuStory.argTypes = {
|
DropdownSelectMenuStory.argTypes = {
|
||||||
align: {
|
align: {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Icon, IconName } from '@/components/Icon';
|
|||||||
|
|
||||||
import { StoryWrapper } from '.ladle/components';
|
import { StoryWrapper } from '.ladle/components';
|
||||||
|
|
||||||
export const IconStory: Story<Parameters<typeof Icon>[0]> = (args) => {
|
export const IconStory: Story<Parameters<typeof Icon>> = (args) => {
|
||||||
return (
|
return (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<Icon {...args} />
|
<Icon {...args} />
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import {
|
|||||||
CoinsIcon,
|
CoinsIcon,
|
||||||
CommentIcon,
|
CommentIcon,
|
||||||
CopyIcon,
|
CopyIcon,
|
||||||
CurrencySignIcon,
|
|
||||||
DepositIcon,
|
DepositIcon,
|
||||||
DepthChartIcon,
|
DepthChartIcon,
|
||||||
DiscordIcon,
|
DiscordIcon,
|
||||||
@@ -36,7 +35,6 @@ import {
|
|||||||
FundingChartIcon,
|
FundingChartIcon,
|
||||||
GearIcon,
|
GearIcon,
|
||||||
GiftboxIcon,
|
GiftboxIcon,
|
||||||
GovernanceIcon,
|
|
||||||
HelpCircleIcon,
|
HelpCircleIcon,
|
||||||
HideIcon,
|
HideIcon,
|
||||||
HistoryIcon,
|
HistoryIcon,
|
||||||
@@ -72,7 +70,6 @@ import {
|
|||||||
StarIcon,
|
StarIcon,
|
||||||
SunIcon,
|
SunIcon,
|
||||||
TerminalIcon,
|
TerminalIcon,
|
||||||
TokenIcon,
|
|
||||||
TradeIcon,
|
TradeIcon,
|
||||||
TransferIcon,
|
TransferIcon,
|
||||||
TriangleIcon,
|
TriangleIcon,
|
||||||
@@ -106,7 +103,6 @@ export enum IconName {
|
|||||||
Coins = 'Coins',
|
Coins = 'Coins',
|
||||||
Comment = 'Comment',
|
Comment = 'Comment',
|
||||||
Copy = 'Copy',
|
Copy = 'Copy',
|
||||||
CurrencySign = 'CurrencySign',
|
|
||||||
Deposit = 'Deposit',
|
Deposit = 'Deposit',
|
||||||
DepthChart = 'DepthChart',
|
DepthChart = 'DepthChart',
|
||||||
Discord = 'Discord',
|
Discord = 'Discord',
|
||||||
@@ -117,7 +113,6 @@ export enum IconName {
|
|||||||
FundingChart = 'FundingChart',
|
FundingChart = 'FundingChart',
|
||||||
Gear = 'Gear',
|
Gear = 'Gear',
|
||||||
Giftbox = 'Giftbox',
|
Giftbox = 'Giftbox',
|
||||||
Governance = 'Governance',
|
|
||||||
HelpCircle = 'HelpCircle',
|
HelpCircle = 'HelpCircle',
|
||||||
Hide = 'Hide',
|
Hide = 'Hide',
|
||||||
History = 'History',
|
History = 'History',
|
||||||
@@ -154,7 +149,6 @@ export enum IconName {
|
|||||||
Sun = 'Sun',
|
Sun = 'Sun',
|
||||||
Terminal = 'Terminal',
|
Terminal = 'Terminal',
|
||||||
TogglesMenu = 'TogglesMenu',
|
TogglesMenu = 'TogglesMenu',
|
||||||
Token = 'Token',
|
|
||||||
Trade = 'Trade',
|
Trade = 'Trade',
|
||||||
Transfer = 'Transfer',
|
Transfer = 'Transfer',
|
||||||
Triangle = 'Triangle',
|
Triangle = 'Triangle',
|
||||||
@@ -188,7 +182,6 @@ const icons = {
|
|||||||
[IconName.Coins]: CoinsIcon,
|
[IconName.Coins]: CoinsIcon,
|
||||||
[IconName.Comment]: CommentIcon,
|
[IconName.Comment]: CommentIcon,
|
||||||
[IconName.Copy]: CopyIcon,
|
[IconName.Copy]: CopyIcon,
|
||||||
[IconName.CurrencySign]: CurrencySignIcon,
|
|
||||||
[IconName.Deposit]: DepositIcon,
|
[IconName.Deposit]: DepositIcon,
|
||||||
[IconName.DepthChart]: DepthChartIcon,
|
[IconName.DepthChart]: DepthChartIcon,
|
||||||
[IconName.Discord]: DiscordIcon,
|
[IconName.Discord]: DiscordIcon,
|
||||||
@@ -199,7 +192,6 @@ const icons = {
|
|||||||
[IconName.FundingChart]: FundingChartIcon,
|
[IconName.FundingChart]: FundingChartIcon,
|
||||||
[IconName.Gear]: GearIcon,
|
[IconName.Gear]: GearIcon,
|
||||||
[IconName.Giftbox]: GiftboxIcon,
|
[IconName.Giftbox]: GiftboxIcon,
|
||||||
[IconName.Governance]: GovernanceIcon,
|
|
||||||
[IconName.HelpCircle]: HelpCircleIcon,
|
[IconName.HelpCircle]: HelpCircleIcon,
|
||||||
[IconName.Hide]: HideIcon,
|
[IconName.Hide]: HideIcon,
|
||||||
[IconName.History]: HistoryIcon,
|
[IconName.History]: HistoryIcon,
|
||||||
@@ -235,7 +227,6 @@ const icons = {
|
|||||||
[IconName.Sun]: SunIcon,
|
[IconName.Sun]: SunIcon,
|
||||||
[IconName.Terminal]: TerminalIcon,
|
[IconName.Terminal]: TerminalIcon,
|
||||||
[IconName.TogglesMenu]: TogglesMenuIcon,
|
[IconName.TogglesMenu]: TogglesMenuIcon,
|
||||||
[IconName.Token]: TokenIcon,
|
|
||||||
[IconName.Trade]: TradeIcon,
|
[IconName.Trade]: TradeIcon,
|
||||||
[IconName.Transfer]: TransferIcon,
|
[IconName.Transfer]: TransferIcon,
|
||||||
[IconName.Triangle]: TriangleIcon,
|
[IconName.Triangle]: TriangleIcon,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { Link } from '@/components/Link';
|
|||||||
import { StoryWrapper } from '.ladle/components';
|
import { StoryWrapper } from '.ladle/components';
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
export const LinkStory: Story<Parameters<typeof Link>[0]> = (args) => {
|
export const LinkStory: Story<Parameters<typeof Link>> = (args) => {
|
||||||
return (
|
return (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<Styled.Container>
|
<Styled.Container>
|
||||||
|
|||||||
@@ -5,24 +5,8 @@ import { HashRouter } from 'react-router-dom';
|
|||||||
|
|
||||||
import { StoryWrapper } from '.ladle/components';
|
import { StoryWrapper } from '.ladle/components';
|
||||||
|
|
||||||
export const NavigationMenuStory: Story<
|
export const NavigationMenuStory: Story<Parameters<typeof NavigationMenu>> = (args) => {
|
||||||
Pick<Parameters<typeof NavigationMenu>[0], 'items' | 'orientation' | 'submenuPlacement'>
|
const exampleItems = [
|
||||||
> = (args) => {
|
|
||||||
return (
|
|
||||||
<StoryWrapper>
|
|
||||||
<HashRouter
|
|
||||||
children={
|
|
||||||
<NavigationMenu {...args}>
|
|
||||||
<span>Menu</span>
|
|
||||||
</NavigationMenu>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</StoryWrapper>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
NavigationMenuStory.args = {
|
|
||||||
items: [
|
|
||||||
{
|
{
|
||||||
group: 'navigation',
|
group: 'navigation',
|
||||||
groupLabel: 'Views',
|
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 = {
|
NavigationMenuStory.argTypes = {
|
||||||
orientation: {
|
orientation: {
|
||||||
options: ['vertical', 'horizontal'],
|
options: ['vertical', 'horizontal'],
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { StoryWrapper } from '.ladle/components';
|
|||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
import { InputType } from './Input';
|
import { InputType } from './Input';
|
||||||
|
|
||||||
export const SearchInputStory: Story<Parameters<typeof SearchInput>[0]> = (args) => (
|
export const SearchInputStory: Story<Parameters<typeof SearchInput>> = (args) => (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<Styled.Container>
|
<Styled.Container>
|
||||||
<SearchInput placeholder="Search something..." type={InputType.Search} />
|
<SearchInput placeholder="Search something..." type={InputType.Search} />
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { SearchSelectMenu } from '@/components/SearchSelectMenu';
|
|||||||
|
|
||||||
import { StoryWrapper } from '.ladle/components';
|
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 [selectedItem, setSelectedItem] = useState<string>();
|
||||||
|
|
||||||
const exampleItems = [
|
const exampleItems = [
|
||||||
@@ -24,7 +24,10 @@ export const SearchSelectMenuStory: Story<Parameters<typeof SearchSelectMenu>[0]
|
|||||||
return (
|
return (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<Container>
|
<Container>
|
||||||
<SearchSelectMenu {...args} items={exampleItems}>
|
<SearchSelectMenu
|
||||||
|
{...args}
|
||||||
|
items={exampleItems}
|
||||||
|
>
|
||||||
{!selectedItem ? <span>Search and Select</span> : <span>{selectedItem}</span>}
|
{!selectedItem ? <span>Search and Select</span> : <span>{selectedItem}</span>}
|
||||||
</SearchSelectMenu>
|
</SearchSelectMenu>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -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 [value, setValue] = useState(exampleItems[0].value);
|
||||||
const [value2, setValue2] = useState(exampleItems[2].value);
|
const [value2, setValue2] = useState(exampleItems[2].value);
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ Styled.Root = styled(Root)`
|
|||||||
--switch-thumb-backgroundColor: var(--color-layer-6);
|
--switch-thumb-backgroundColor: var(--color-layer-6);
|
||||||
|
|
||||||
--switch-active-backgroundColor: var(--color-accent);
|
--switch-active-backgroundColor: var(--color-accent);
|
||||||
--switch-active-thumb-backgroundColor: var(--color-white);
|
--switch-active-thumb-backgroundColor: ${({ theme }) => theme.switchThumbActiveBackground};
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
width: var(--switch-width);
|
width: var(--switch-width);
|
||||||
|
|||||||
@@ -13,11 +13,29 @@ enum TabItem {
|
|||||||
Item3 = 'Item3',
|
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 (
|
return (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<Styled.Container>
|
<Styled.Container>
|
||||||
<Tabs {...args} />
|
<Tabs items={TabItems} {...args} />
|
||||||
</Styled.Container>
|
</Styled.Container>
|
||||||
</StoryWrapper>
|
</StoryWrapper>
|
||||||
);
|
);
|
||||||
@@ -25,23 +43,6 @@ export const TabsStory: Story<Parameters<typeof Tabs>[0]> = (args) => {
|
|||||||
|
|
||||||
TabsStory.args = {
|
TabsStory.args = {
|
||||||
fullWidthTabs: false,
|
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 = {
|
TabsStory.argTypes = {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { Story } from '@ladle/react';
|
import type { Story } from '@ladle/react';
|
||||||
|
|
||||||
import { Tag, TagSign, TagSize, TagType } from '@/components/Tag';
|
import { Tag } from '@/components/Tag';
|
||||||
|
|
||||||
import { StoryWrapper } from '.ladle/components';
|
import { StoryWrapper } from '.ladle/components';
|
||||||
|
|
||||||
export const TagStory: Story<Parameters<typeof Tag>[0]> = (args) => {
|
export const TagStory: Story<Parameters<typeof Tag>> = (args) => {
|
||||||
return (
|
return (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<Tag {...args} />
|
<Tag {...args} />
|
||||||
@@ -14,23 +14,4 @@ export const TagStory: Story<Parameters<typeof Tag>[0]> = (args) => {
|
|||||||
|
|
||||||
TagStory.args = {
|
TagStory.args = {
|
||||||
children: 'USDC',
|
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,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import styled, { css } from 'styled-components';
|
import styled, { css } from 'styled-components';
|
||||||
|
|
||||||
export enum TagSize {
|
export enum TagSize {
|
||||||
Small = 'Small',
|
Small,
|
||||||
Medium = 'Medium',
|
Medium,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TagType {
|
export enum TagType {
|
||||||
Asset = 'Asset',
|
Asset,
|
||||||
Side = 'Side',
|
Side,
|
||||||
Number = 'Number',
|
Number,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TagSign {
|
export enum TagSign {
|
||||||
Positive = 'Positive',
|
Positive,
|
||||||
Negative = 'Negative',
|
Negative,
|
||||||
Neutral = 'Neutral',
|
Neutral,
|
||||||
}
|
}
|
||||||
|
|
||||||
type StyleProps = {
|
type StyleProps = {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { ButtonShape, ButtonSize } from '@/constants/buttons';
|
|||||||
import { StoryWrapper } from '.ladle/components';
|
import { StoryWrapper } from '.ladle/components';
|
||||||
import { ToggleButton } from './ToggleButton';
|
import { ToggleButton } from './ToggleButton';
|
||||||
|
|
||||||
export const ToggleButtonStory: Story<Parameters<typeof ToggleButton>[0]> = (args) => (
|
export const ToggleButtonStory: Story<Parameters<typeof ToggleButton>> = (args) => (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<ToggleButton {...args}>Toggle me</ToggleButton>
|
<ToggleButton {...args}>Toggle me</ToggleButton>
|
||||||
</StoryWrapper>
|
</StoryWrapper>
|
||||||
|
|||||||
@@ -21,22 +21,16 @@ const ToggleGroupItems = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const ToggleGroupStory: Story<
|
export const ToggleGroupStory: Story<Parameters<typeof ToggleGroup>> = (args) => {
|
||||||
Pick<Parameters<typeof ToggleGroup>[0], 'items' | 'size' | 'shape'>
|
|
||||||
> = (args) => {
|
|
||||||
const [value, setValue] = useState('0');
|
const [value, setValue] = useState('0');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<ToggleGroup value={value} onValueChange={setValue} {...args} />
|
<ToggleGroup items={ToggleGroupItems} value={value} onValueChange={setValue} {...args} />
|
||||||
</StoryWrapper>
|
</StoryWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
ToggleGroupStory.args = {
|
|
||||||
items: ToggleGroupItems,
|
|
||||||
};
|
|
||||||
|
|
||||||
ToggleGroupStory.argTypes = {
|
ToggleGroupStory.argTypes = {
|
||||||
size: {
|
size: {
|
||||||
options: Object.values(ButtonSize),
|
options: Object.values(ButtonSize),
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ Styled.ConfirmButton = styled(Styled.IconButton)`
|
|||||||
--button-backgroundColor: hsla(203, 25%, 19%, 1);
|
--button-backgroundColor: hsla(203, 25%, 19%, 1);
|
||||||
|
|
||||||
svg {
|
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);
|
--button-backgroundColor: hsla(296, 16%, 18%, 1);
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
color: var(--color-red);
|
color: var(--color-error);
|
||||||
width: 0.8em;
|
width: 0.8em;
|
||||||
height: 0.8em;
|
height: 0.8em;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { StoryWrapper } from '.ladle/components';
|
|||||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
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 [firstName, setFirstName] = useState('');
|
||||||
const [lastName, setLastName] = useState('');
|
const [lastName, setLastName] = useState('');
|
||||||
|
|
||||||
|
|||||||
@@ -3,29 +3,32 @@ import type { Story } from '@ladle/react';
|
|||||||
import { Button } from '@/components/Button';
|
import { Button } from '@/components/Button';
|
||||||
|
|
||||||
import { WithReceipt } from '@/components/WithReceipt';
|
import { WithReceipt } from '@/components/WithReceipt';
|
||||||
|
import { type DetailsItem } from './Details';
|
||||||
|
|
||||||
import { StoryWrapper } from '.ladle/components';
|
import { StoryWrapper } from '.ladle/components';
|
||||||
|
|
||||||
export const WithReceiptStory: Story<Omit<Parameters<typeof WithReceipt>[0], 'slotReceipt'>> = (
|
const items: DetailsItem[] = [
|
||||||
args
|
{
|
||||||
) => (
|
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>
|
<StoryWrapper>
|
||||||
<div style={{ width: 200 }}>
|
<div style={{ width: 200 }}>
|
||||||
<WithReceipt
|
<WithReceipt {...args}>
|
||||||
slotReceipt={
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
padding: '1rem',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Receipt Content
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{...args}
|
|
||||||
>
|
|
||||||
<Button>Hello there</Button>
|
<Button>Hello there</Button>
|
||||||
</WithReceipt>
|
</WithReceipt>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,7 +36,7 @@ export const WithReceiptStory: Story<Omit<Parameters<typeof WithReceipt>[0], 'sl
|
|||||||
);
|
);
|
||||||
|
|
||||||
WithReceiptStory.args = {
|
WithReceiptStory.args = {
|
||||||
hideReceipt: false,
|
items,
|
||||||
};
|
};
|
||||||
|
|
||||||
WithReceiptStory.argTypes = {
|
WithReceiptStory.argTypes = {
|
||||||
|
|||||||
@@ -106,6 +106,8 @@ Styled.Container = styled.div`
|
|||||||
--stickyArea1-leftGap: var(--border-width);
|
--stickyArea1-leftGap: var(--border-width);
|
||||||
min-height: var(--stickyArea-height);
|
min-height: var(--stickyArea-height);
|
||||||
|
|
||||||
|
${layoutMixins.withOuterAndInnerBorders}
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template: var(--withSidebar-gridTemplate);
|
grid-template: var(--withSidebar-gridTemplate);
|
||||||
`;
|
`;
|
||||||
@@ -118,7 +120,6 @@ Styled.Side = styled.aside`
|
|||||||
${layoutMixins.sticky}
|
${layoutMixins.sticky}
|
||||||
max-height: var(--stickyArea-height);
|
max-height: var(--stickyArea-height);
|
||||||
backdrop-filter: none;
|
backdrop-filter: none;
|
||||||
background-color: var(--color-layer-2);
|
|
||||||
|
|
||||||
${layoutMixins.stack}
|
${layoutMixins.stack}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { tooltipStrings } from '@/constants/tooltips';
|
|||||||
|
|
||||||
import { StoryWrapper } from '.ladle/components';
|
import { StoryWrapper } from '.ladle/components';
|
||||||
|
|
||||||
export const Tooltip: Story<Parameters<typeof WithTooltip>[0]> = (args) => {
|
export const Tooltip: Story<Parameters<typeof WithTooltip>> = (args) => {
|
||||||
return (
|
return (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<WithTooltip {...args}>
|
<WithTooltip {...args}>
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ export enum DialogTypes {
|
|||||||
DisplaySettings = 'DisplaySettings',
|
DisplaySettings = 'DisplaySettings',
|
||||||
ExchangeOffline = 'ExchangeOffline',
|
ExchangeOffline = 'ExchangeOffline',
|
||||||
ExternalLink = 'ExternalLink',
|
ExternalLink = 'ExternalLink',
|
||||||
ExternalNavStride = 'ExternalNavStride',
|
|
||||||
FillDetails = 'FillDetails',
|
FillDetails = 'FillDetails',
|
||||||
Help = 'Help',
|
Help = 'Help',
|
||||||
ExternalNavKeplr = 'ExternalNavKeplr',
|
ExternalNavKeplr = 'ExternalNavKeplr',
|
||||||
|
|||||||
@@ -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 = {
|
export type ExchangeConfigItem = {
|
||||||
exchangeName: string;
|
exchangeName: string;
|
||||||
ticker: string;
|
ticker: string;
|
||||||
adjustByMarket?: 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 = {
|
export type PotentialMarketItem = {
|
||||||
baseAsset: string;
|
baseAsset: string;
|
||||||
referencePrice: string;
|
referencePrice: string;
|
||||||
@@ -23,3 +56,30 @@ export type PotentialMarketItem = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const NUM_ORACLES_TO_QUALIFY_AS_SAFE = 6;
|
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,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|||||||
@@ -29,12 +29,6 @@ export enum HistoryRoute {
|
|||||||
Payments = 'payments',
|
Payments = 'payments',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TokenRoute {
|
|
||||||
TradingRewards = 'trading-rewards',
|
|
||||||
StakingRewards = 'staking-rewards',
|
|
||||||
Governance = 'governance',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum MobileSettingsRoute {
|
export enum MobileSettingsRoute {
|
||||||
Language = 'language',
|
Language = 'language',
|
||||||
Notifications = 'notifications',
|
Notifications = 'notifications',
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ export type Theme = {
|
|||||||
[AppColorMode.RedUp]: ThemeColorBase;
|
[AppColorMode.RedUp]: ThemeColorBase;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ThemeColorBase = BaseColors &
|
export type ThemeColorBase = LayerColors &
|
||||||
LayerColors &
|
|
||||||
BorderColors &
|
BorderColors &
|
||||||
TextColors &
|
TextColors &
|
||||||
GradientColors &
|
GradientColors &
|
||||||
@@ -18,12 +17,6 @@ export type ThemeColorBase = BaseColors &
|
|||||||
ComponentColors &
|
ComponentColors &
|
||||||
Filters;
|
Filters;
|
||||||
|
|
||||||
type BaseColors = {
|
|
||||||
white: string;
|
|
||||||
green: string;
|
|
||||||
red: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type LayerColors = {
|
type LayerColors = {
|
||||||
layer0: string;
|
layer0: string;
|
||||||
layer1: string;
|
layer1: string;
|
||||||
@@ -93,6 +86,7 @@ type IconColors = {
|
|||||||
type ComponentColors = {
|
type ComponentColors = {
|
||||||
inputBackground: string;
|
inputBackground: string;
|
||||||
popoverBackground: string;
|
popoverBackground: string;
|
||||||
|
switchThumbActiveBackground: string;
|
||||||
toggleBackground: string;
|
toggleBackground: string;
|
||||||
tooltipBackground: string;
|
tooltipBackground: string;
|
||||||
};
|
};
|
||||||
|
|||||||
+20
-54
@@ -4,6 +4,7 @@ import { AlertType } from '@/constants/alerts';
|
|||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
import { TimeUnitShort } from '@/constants/time';
|
import { TimeUnitShort } from '@/constants/time';
|
||||||
|
|
||||||
|
// TODO: rename to OrderType
|
||||||
export enum TradeTypes {
|
export enum TradeTypes {
|
||||||
MARKET = 'MARKET',
|
MARKET = 'MARKET',
|
||||||
LIMIT = 'LIMIT',
|
LIMIT = 'LIMIT',
|
||||||
@@ -14,16 +15,6 @@ export enum TradeTypes {
|
|||||||
TRAILING_STOP = 'TRAILING_STOP',
|
TRAILING_STOP = 'TRAILING_STOP',
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ClosingTradeTypes {
|
|
||||||
LIQUIDATED = 'LIQUIDATED',
|
|
||||||
LIQUIDATION = 'LIQUIDATION',
|
|
||||||
OFFSETTING = 'OFFSETTING',
|
|
||||||
DELEVERAGED = 'DELEVERAGED',
|
|
||||||
FINAL_SETTLEMENT = 'FINAL_SETTLEMENT',
|
|
||||||
}
|
|
||||||
|
|
||||||
export type OrderType = TradeTypes | ClosingTradeTypes;
|
|
||||||
|
|
||||||
export enum TimeInForceOptions {
|
export enum TimeInForceOptions {
|
||||||
GTT = 'GTT',
|
GTT = 'GTT',
|
||||||
FOK = 'FOK',
|
FOK = 'FOK',
|
||||||
@@ -49,74 +40,49 @@ export const POSITION_SIDE_STRINGS: Record<PositionSide, string> = {
|
|||||||
[PositionSide.Short]: STRING_KEYS.SHORT_POSITION_SHORT,
|
[PositionSide.Short]: STRING_KEYS.SHORT_POSITION_SHORT,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ORDER_TYPE_STRINGS: Record<
|
export const TRADE_TYPE_STRINGS: Record<
|
||||||
OrderType,
|
TradeTypes,
|
||||||
{
|
{
|
||||||
orderTypeKeyShort: string;
|
tradeTypeKeyShort: string;
|
||||||
orderTypeKey: string;
|
tradeTypeKey: string;
|
||||||
descriptionKey: string | null;
|
descriptionKey: string;
|
||||||
}
|
}
|
||||||
> = {
|
> = {
|
||||||
[TradeTypes.LIMIT]: {
|
[TradeTypes.LIMIT]: {
|
||||||
orderTypeKeyShort: STRING_KEYS.LIMIT_ORDER_SHORT,
|
tradeTypeKeyShort: STRING_KEYS.LIMIT_ORDER_SHORT,
|
||||||
orderTypeKey: STRING_KEYS.LIMIT_ORDER,
|
tradeTypeKey: STRING_KEYS.LIMIT_ORDER,
|
||||||
descriptionKey: STRING_KEYS.LIMIT_ORDER_DESCRIPTION,
|
descriptionKey: STRING_KEYS.LIMIT_ORDER_DESCRIPTION,
|
||||||
},
|
},
|
||||||
[TradeTypes.MARKET]: {
|
[TradeTypes.MARKET]: {
|
||||||
orderTypeKeyShort: STRING_KEYS.MARKET_ORDER_SHORT,
|
tradeTypeKeyShort: STRING_KEYS.MARKET_ORDER_SHORT,
|
||||||
orderTypeKey: STRING_KEYS.MARKET_ORDER,
|
tradeTypeKey: STRING_KEYS.MARKET_ORDER,
|
||||||
descriptionKey: STRING_KEYS.MARKET_ORDER_DESCRIPTION,
|
descriptionKey: STRING_KEYS.MARKET_ORDER_DESCRIPTION,
|
||||||
},
|
},
|
||||||
[TradeTypes.STOP_LIMIT]: {
|
[TradeTypes.STOP_LIMIT]: {
|
||||||
orderTypeKeyShort: STRING_KEYS.STOP_LIMIT,
|
tradeTypeKeyShort: STRING_KEYS.STOP_LIMIT,
|
||||||
orderTypeKey: STRING_KEYS.STOP_LIMIT,
|
tradeTypeKey: STRING_KEYS.STOP_LIMIT,
|
||||||
descriptionKey: STRING_KEYS.STOP_LIMIT_DESCRIPTION,
|
descriptionKey: STRING_KEYS.STOP_LIMIT_DESCRIPTION,
|
||||||
},
|
},
|
||||||
[TradeTypes.STOP_MARKET]: {
|
[TradeTypes.STOP_MARKET]: {
|
||||||
orderTypeKeyShort: STRING_KEYS.STOP_MARKET,
|
tradeTypeKeyShort: STRING_KEYS.STOP_MARKET,
|
||||||
orderTypeKey: STRING_KEYS.STOP_MARKET,
|
tradeTypeKey: STRING_KEYS.STOP_MARKET,
|
||||||
descriptionKey: STRING_KEYS.STOP_MARKET_DESCRIPTION,
|
descriptionKey: STRING_KEYS.STOP_MARKET_DESCRIPTION,
|
||||||
},
|
},
|
||||||
[TradeTypes.TAKE_PROFIT]: {
|
[TradeTypes.TAKE_PROFIT]: {
|
||||||
orderTypeKeyShort: STRING_KEYS.TAKE_PROFIT_LIMIT,
|
tradeTypeKeyShort: STRING_KEYS.TAKE_PROFIT_LIMIT,
|
||||||
orderTypeKey: STRING_KEYS.TAKE_PROFIT_LIMIT,
|
tradeTypeKey: STRING_KEYS.TAKE_PROFIT_LIMIT,
|
||||||
descriptionKey: STRING_KEYS.TAKE_PROFIT_LIMIT_DESCRIPTION,
|
descriptionKey: STRING_KEYS.TAKE_PROFIT_LIMIT_DESCRIPTION,
|
||||||
},
|
},
|
||||||
[TradeTypes.TAKE_PROFIT_MARKET]: {
|
[TradeTypes.TAKE_PROFIT_MARKET]: {
|
||||||
orderTypeKeyShort: STRING_KEYS.TAKE_PROFIT_MARKET,
|
tradeTypeKeyShort: STRING_KEYS.TAKE_PROFIT_MARKET,
|
||||||
orderTypeKey: STRING_KEYS.TAKE_PROFIT_MARKET,
|
tradeTypeKey: STRING_KEYS.TAKE_PROFIT_MARKET,
|
||||||
descriptionKey: STRING_KEYS.TAKE_PROFIT_MARKET_DESCRIPTION,
|
descriptionKey: STRING_KEYS.TAKE_PROFIT_MARKET_DESCRIPTION,
|
||||||
},
|
},
|
||||||
[TradeTypes.TRAILING_STOP]: {
|
[TradeTypes.TRAILING_STOP]: {
|
||||||
orderTypeKeyShort: STRING_KEYS.TRAILING_STOP,
|
tradeTypeKeyShort: STRING_KEYS.TRAILING_STOP,
|
||||||
orderTypeKey: STRING_KEYS.TRAILING_STOP,
|
tradeTypeKey: STRING_KEYS.TRAILING_STOP,
|
||||||
descriptionKey: STRING_KEYS.TRAILING_STOP_DESCRIPTION,
|
descriptionKey: STRING_KEYS.TRAILING_STOP_DESCRIPTION,
|
||||||
},
|
},
|
||||||
[ClosingTradeTypes.LIQUIDATED]: {
|
|
||||||
orderTypeKeyShort: STRING_KEYS.LIQUIDATED,
|
|
||||||
orderTypeKey: STRING_KEYS.LIQUIDATED,
|
|
||||||
descriptionKey: null,
|
|
||||||
},
|
|
||||||
[ClosingTradeTypes.LIQUIDATION]: {
|
|
||||||
orderTypeKeyShort: STRING_KEYS.LIQUIDATION,
|
|
||||||
orderTypeKey: STRING_KEYS.LIQUIDATION,
|
|
||||||
descriptionKey: null,
|
|
||||||
},
|
|
||||||
[ClosingTradeTypes.OFFSETTING]: {
|
|
||||||
orderTypeKeyShort: STRING_KEYS.OFFSETTING,
|
|
||||||
orderTypeKey: STRING_KEYS.OFFSETTING,
|
|
||||||
descriptionKey: null,
|
|
||||||
},
|
|
||||||
[ClosingTradeTypes.DELEVERAGED]: {
|
|
||||||
orderTypeKeyShort: STRING_KEYS.DELEVERAGED,
|
|
||||||
orderTypeKey: STRING_KEYS.DELEVERAGED,
|
|
||||||
descriptionKey: null,
|
|
||||||
},
|
|
||||||
[ClosingTradeTypes.FINAL_SETTLEMENT]: {
|
|
||||||
orderTypeKeyShort: STRING_KEYS.FINAL_SETTLEMENT,
|
|
||||||
orderTypeKey: STRING_KEYS.FINAL_SETTLEMENT,
|
|
||||||
descriptionKey: null,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GOOD_TIL_TIME_TIMESCALE_STRINGS: Record<TimeUnitShort, string> = {
|
export const GOOD_TIL_TIME_TIMESCALE_STRINGS: Record<TimeUnitShort, string> = {
|
||||||
|
|||||||
@@ -5,11 +5,9 @@ import isEmpty from 'lodash/isEmpty';
|
|||||||
import { LanguageCode, ResolutionString, widget } from 'public/tradingview/charting_library';
|
import { LanguageCode, ResolutionString, widget } from 'public/tradingview/charting_library';
|
||||||
|
|
||||||
import { DEFAULT_RESOLUTION } from '@/constants/candles';
|
import { DEFAULT_RESOLUTION } from '@/constants/candles';
|
||||||
import { SUPPORTED_LOCALE_BASE_TAGS, STRING_KEYS } from '@/constants/localization';
|
import { SUPPORTED_LOCALE_BASE_TAGS } from '@/constants/localization';
|
||||||
|
|
||||||
import { LocalStorageKey } from '@/constants/localStorage';
|
import { LocalStorageKey } from '@/constants/localStorage';
|
||||||
|
import { useDydxClient, useLocalStorage } from '@/hooks';
|
||||||
import { useDydxClient, useLocalStorage, useStringGetter } from '@/hooks';
|
|
||||||
import { store } from '@/state/_store';
|
import { store } from '@/state/_store';
|
||||||
|
|
||||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||||
@@ -25,19 +23,14 @@ import { getSavedResolution, getWidgetOptions, getWidgetOverrides } from '@/lib/
|
|||||||
*/
|
*/
|
||||||
export const useTradingView = ({
|
export const useTradingView = ({
|
||||||
tvWidgetRef,
|
tvWidgetRef,
|
||||||
displayButtonRef,
|
|
||||||
setIsChartReady,
|
setIsChartReady,
|
||||||
}: {
|
}: {
|
||||||
tvWidgetRef: React.MutableRefObject<any>;
|
tvWidgetRef: React.MutableRefObject<any>;
|
||||||
displayButtonRef: React.MutableRefObject<any>;
|
|
||||||
setIsChartReady: React.Dispatch<React.SetStateAction<boolean>>;
|
setIsChartReady: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
}) => {
|
}) => {
|
||||||
const stringGetter = useStringGetter();
|
const marketId = useSelector(getCurrentMarketId);
|
||||||
|
|
||||||
const appTheme = useSelector(getAppTheme);
|
const appTheme = useSelector(getAppTheme);
|
||||||
const appColorMode = useSelector(getAppColorMode);
|
const appColorMode = useSelector(getAppColorMode);
|
||||||
|
|
||||||
const marketId = useSelector(getCurrentMarketId);
|
|
||||||
const marketIds = useSelector(getMarketIds, shallowEqual);
|
const marketIds = useSelector(getMarketIds, shallowEqual);
|
||||||
const selectedLocale = useSelector(getSelectedLocale);
|
const selectedLocale = useSelector(getSelectedLocale);
|
||||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||||
@@ -56,6 +49,7 @@ export const useTradingView = ({
|
|||||||
const widgetOptions = getWidgetOptions();
|
const widgetOptions = getWidgetOptions();
|
||||||
const widgetOverrides = getWidgetOverrides({ appTheme, appColorMode });
|
const widgetOverrides = getWidgetOverrides({ appTheme, appColorMode });
|
||||||
const options = {
|
const options = {
|
||||||
|
// debug: true,
|
||||||
...widgetOptions,
|
...widgetOptions,
|
||||||
...widgetOverrides,
|
...widgetOverrides,
|
||||||
datafeed: getDydxDatafeed(store, getCandlesForDatafeed),
|
datafeed: getDydxDatafeed(store, getCandlesForDatafeed),
|
||||||
@@ -69,17 +63,6 @@ export const useTradingView = ({
|
|||||||
tvWidgetRef.current = tvChartWidget;
|
tvWidgetRef.current = tvChartWidget;
|
||||||
|
|
||||||
tvWidgetRef.current.onChartReady(() => {
|
tvWidgetRef.current.onChartReady(() => {
|
||||||
tvWidgetRef?.current?.headerReady().then(() => {
|
|
||||||
displayButtonRef.current = tvWidgetRef?.current?.createButton();
|
|
||||||
displayButtonRef.current.innerHTML = `<span>${stringGetter({
|
|
||||||
key: STRING_KEYS.ORDER_LINES,
|
|
||||||
})}</span> <div class="displayOrdersButton-toggle"></div>`;
|
|
||||||
displayButtonRef.current.setAttribute(
|
|
||||||
'title',
|
|
||||||
stringGetter({ key: STRING_KEYS.ORDER_LINES_TOOLTIP })
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
tvWidgetRef?.current?.subscribe('onAutoSaveNeeded', () =>
|
tvWidgetRef?.current?.subscribe('onAutoSaveNeeded', () =>
|
||||||
tvWidgetRef?.current?.save((chartConfig: object) => setTvChartConfig(chartConfig))
|
tvWidgetRef?.current?.save((chartConfig: object) => setTvChartConfig(chartConfig))
|
||||||
);
|
);
|
||||||
@@ -89,8 +72,6 @@ export const useTradingView = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
displayButtonRef.current?.remove();
|
|
||||||
displayButtonRef.current = null;
|
|
||||||
tvWidgetRef.current?.remove();
|
tvWidgetRef.current?.remove();
|
||||||
tvWidgetRef.current = null;
|
tvWidgetRef.current = null;
|
||||||
setIsChartReady(false);
|
setIsChartReady(false);
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
import type {
|
import type { IChartingLibraryWidget, ThemeName } from 'public/tradingview/charting_library';
|
||||||
IChartingLibraryWidget,
|
|
||||||
IOrderLineAdapter,
|
|
||||||
ThemeName,
|
|
||||||
} from 'public/tradingview/charting_library';
|
|
||||||
|
|
||||||
import { AppColorMode, AppTheme } from '@/state/configs';
|
import { AppColorMode, AppTheme } from '@/state/configs';
|
||||||
import { getAppTheme, getAppColorMode } from '@/state/configsSelectors';
|
import { getAppTheme, getAppColorMode } from '@/state/configsSelectors';
|
||||||
|
|
||||||
import { getWidgetOverrides, getOrderLineColors } from '@/lib/tradingView/utils';
|
import { getWidgetOverrides } from '@/lib/tradingView/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Method to define a type guard and check that an element is an IFRAME
|
* @description Method to define a type guard and check that an element is an IFRAME
|
||||||
@@ -26,11 +22,9 @@ const isIFrame = (element: HTMLElement | null): element is HTMLIFrameElement =>
|
|||||||
* In order to support our Classic along with Dark/Light, we are directly accessing the <html> within the iFrame.
|
* In order to support our Classic along with Dark/Light, we are directly accessing the <html> within the iFrame.
|
||||||
*/
|
*/
|
||||||
export const useTradingViewTheme = ({
|
export const useTradingViewTheme = ({
|
||||||
orderLines,
|
|
||||||
tvWidget,
|
tvWidget,
|
||||||
isWidgetReady,
|
isWidgetReady,
|
||||||
}: {
|
}: {
|
||||||
orderLines: Record<string, IOrderLineAdapter>;
|
|
||||||
tvWidget: (IChartingLibraryWidget & { _id?: string; _ready?: boolean }) | null;
|
tvWidget: (IChartingLibraryWidget & { _id?: string; _ready?: boolean }) | null;
|
||||||
isWidgetReady?: boolean;
|
isWidgetReady?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
@@ -43,8 +37,8 @@ export const useTradingViewTheme = ({
|
|||||||
.changeTheme?.(
|
.changeTheme?.(
|
||||||
{
|
{
|
||||||
[AppTheme.Classic]: '',
|
[AppTheme.Classic]: '',
|
||||||
[AppTheme.Dark]: 'dark',
|
[AppTheme.Dark]: 'Dark',
|
||||||
[AppTheme.Light]: 'light',
|
[AppTheme.Light]: 'Light',
|
||||||
}[appTheme] as ThemeName
|
}[appTheme] as ThemeName
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -55,17 +49,9 @@ export const useTradingViewTheme = ({
|
|||||||
|
|
||||||
if (isIFrame(frame) && frame.contentWindow) {
|
if (isIFrame(frame) && frame.contentWindow) {
|
||||||
const innerHtml = frame.contentWindow.document.documentElement;
|
const innerHtml = frame.contentWindow.document.documentElement;
|
||||||
switch (appTheme) {
|
|
||||||
case AppTheme.Classic:
|
if (appTheme === AppTheme.Classic) {
|
||||||
innerHtml?.classList.remove('theme-dark', 'theme-light');
|
innerHtml?.classList.remove('theme-dark', 'theme-light');
|
||||||
break;
|
|
||||||
case AppTheme.Dark:
|
|
||||||
innerHtml?.classList.remove('theme-light');
|
|
||||||
innerHtml?.classList.add('theme-dark');
|
|
||||||
break;
|
|
||||||
case AppTheme.Light:
|
|
||||||
innerHtml?.classList.remove('theme-dark');
|
|
||||||
innerHtml?.classList.add('theme-light');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,22 +73,7 @@ export const useTradingViewTheme = ({
|
|||||||
'volume.color.1': studies_overrides['volume.volume.color.1'],
|
'volume.color.1': studies_overrides['volume.volume.color.1'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Necessary to update existing chart lines
|
|
||||||
Object.entries(orderLines).forEach(([key, line]) => {
|
|
||||||
const { orderColor, borderColor, backgroundColor, textColor, textButtonColor } =
|
|
||||||
getOrderLineColors({ side: key.split('-')[0], appTheme, appColorMode });
|
|
||||||
|
|
||||||
line
|
|
||||||
.setLineColor(orderColor)
|
|
||||||
.setQuantityBackgroundColor(orderColor)
|
|
||||||
.setQuantityBorderColor(borderColor)
|
|
||||||
.setBodyBackgroundColor(backgroundColor)
|
|
||||||
.setBodyBorderColor(borderColor)
|
|
||||||
.setBodyTextColor(textColor)
|
|
||||||
.setQuantityTextColor(textButtonColor);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [appTheme, appColorMode, isWidgetReady]);
|
}, [appTheme, appColorMode]);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const useMarketsData = (
|
|||||||
return Object.values(allPerpetualMarkets)
|
return Object.values(allPerpetualMarkets)
|
||||||
.filter(isTruthy)
|
.filter(isTruthy)
|
||||||
.map((marketData) => ({
|
.map((marketData) => ({
|
||||||
asset: allAssets[marketData.assetId] ?? {},
|
asset: allAssets[marketData.assetId],
|
||||||
tickSizeDecimals: marketData.configs?.tickSizeDecimals,
|
tickSizeDecimals: marketData.configs?.tickSizeDecimals,
|
||||||
...marketData,
|
...marketData,
|
||||||
...marketData.perpetual,
|
...marketData.perpetual,
|
||||||
@@ -46,10 +46,9 @@ export const useMarketsData = (
|
|||||||
|
|
||||||
if (searchFilter) {
|
if (searchFilter) {
|
||||||
return filtered.filter(
|
return filtered.filter(
|
||||||
({ asset, id }) =>
|
({ asset }) =>
|
||||||
asset?.name?.toLocaleLowerCase().includes(searchFilter.toLowerCase()) ||
|
asset?.name?.toLocaleLowerCase().includes(searchFilter.toLowerCase()) ||
|
||||||
asset?.id?.toLocaleLowerCase().includes(searchFilter.toLowerCase()) ||
|
asset?.id?.toLocaleLowerCase().includes(searchFilter.toLowerCase())
|
||||||
id?.toLocaleLowerCase().includes(searchFilter.toLowerCase())
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return filtered;
|
return filtered;
|
||||||
|
|||||||
@@ -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 {
|
||||||
import type { ExchangeConfigItem, PotentialMarketItem } from '@/constants/potentialMarkets';
|
ExchangeConfigItem,
|
||||||
|
ExchangeConfigParsedCsv,
|
||||||
|
PotentialMarketItem,
|
||||||
|
PotentialMarketParsedCsv,
|
||||||
|
} from '@/constants/potentialMarkets';
|
||||||
|
|
||||||
import { log } from '@/lib/telemetry';
|
import { log } from '@/lib/telemetry';
|
||||||
|
|
||||||
import { useStringGetter } from './useStringGetter';
|
|
||||||
|
|
||||||
const PotentialMarketsContext = createContext<ReturnType<typeof usePotentialMarketsContext>>({
|
const PotentialMarketsContext = createContext<ReturnType<typeof usePotentialMarketsContext>>({
|
||||||
potentialMarkets: undefined,
|
potentialMarkets: undefined,
|
||||||
exchangeConfigs: undefined,
|
exchangeConfigs: undefined,
|
||||||
hasPotentialMarketsData: false,
|
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';
|
PotentialMarketsContext.displayName = 'PotentialMarkets';
|
||||||
@@ -51,7 +27,6 @@ const EXCHANGE_CONFIG_FILE_PATH = '/configs/potentialMarketExchangeConfig.json';
|
|||||||
const POTENTIAL_MARKETS_FILE_PATH = '/configs/potentialMarketParameters.json';
|
const POTENTIAL_MARKETS_FILE_PATH = '/configs/potentialMarketParameters.json';
|
||||||
|
|
||||||
export const usePotentialMarketsContext = () => {
|
export const usePotentialMarketsContext = () => {
|
||||||
const stringGetter = useStringGetter();
|
|
||||||
const [potentialMarkets, setPotentialMarkets] = useState<PotentialMarketItem[]>();
|
const [potentialMarkets, setPotentialMarkets] = useState<PotentialMarketItem[]>();
|
||||||
const [exchangeConfigs, setExchangeConfigs] = useState<Record<string, ExchangeConfigItem[]>>();
|
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: '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 {
|
return {
|
||||||
potentialMarkets,
|
potentialMarkets,
|
||||||
exchangeConfigs,
|
exchangeConfigs,
|
||||||
hasPotentialMarketsData: Boolean(potentialMarkets && exchangeConfigs),
|
hasPotentialMarketsData: Boolean(potentialMarkets && exchangeConfigs),
|
||||||
liquidityTiers,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
+17
-21
@@ -5,25 +5,23 @@ import { useSelectedNetwork } from '@/hooks';
|
|||||||
const FALLBACK_URL = 'https://help.dydx.exchange/';
|
const FALLBACK_URL = 'https://help.dydx.exchange/';
|
||||||
|
|
||||||
export interface LinksConfigs {
|
export interface LinksConfigs {
|
||||||
tos: string;
|
tos: string,
|
||||||
privacy: string;
|
privacy: string,
|
||||||
mintscan: string;
|
mintscan: string,
|
||||||
mintscanBase: string;
|
mintscanBase: string,
|
||||||
feedback?: string;
|
feedback?: string,
|
||||||
help?: string;
|
help?: string,
|
||||||
blogs?: string;
|
blogs?: string,
|
||||||
foundation?: string;
|
foundation?: string,
|
||||||
initialMarginFractionLearnMore?: string;
|
initialMarginFractionLearnMore?: string,
|
||||||
reduceOnlyLearnMore?: string;
|
reduceOnlyLearnMore?: string,
|
||||||
documentation?: string;
|
documentation?: string,
|
||||||
community?: string;
|
community?: string,
|
||||||
governanceLearnMore?: string;
|
governanceLearnMore?: string,
|
||||||
newMarketProposalLearnMore: string;
|
stakingLearnMore?: string,
|
||||||
stakingLearnMore?: string;
|
keplrDashboard?: string,
|
||||||
keplrDashboard?: string;
|
accountExportLearnMore?: string,
|
||||||
strideZoneApp?: string;
|
walletLearnMore?: string
|
||||||
accountExportLearnMore?: string;
|
|
||||||
walletLearnMore?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useURLConfigs = (): LinksConfigs => {
|
export const useURLConfigs = (): LinksConfigs => {
|
||||||
@@ -44,10 +42,8 @@ export const useURLConfigs = (): LinksConfigs => {
|
|||||||
documentation: linksConfigs.documentation || FALLBACK_URL,
|
documentation: linksConfigs.documentation || FALLBACK_URL,
|
||||||
community: linksConfigs.community || FALLBACK_URL,
|
community: linksConfigs.community || FALLBACK_URL,
|
||||||
governanceLearnMore: linksConfigs.governanceLearnMore || FALLBACK_URL,
|
governanceLearnMore: linksConfigs.governanceLearnMore || FALLBACK_URL,
|
||||||
newMarketProposalLearnMore: linksConfigs.newMarketProposalLearnMore || FALLBACK_URL,
|
|
||||||
stakingLearnMore: linksConfigs.stakingLearnMore || FALLBACK_URL,
|
stakingLearnMore: linksConfigs.stakingLearnMore || FALLBACK_URL,
|
||||||
keplrDashboard: linksConfigs.keplrDashboard || FALLBACK_URL,
|
keplrDashboard: linksConfigs.keplrDashboard || FALLBACK_URL,
|
||||||
strideZoneApp: linksConfigs.strideZoneApp || FALLBACK_URL,
|
|
||||||
accountExportLearnMore: linksConfigs.accountExportLearnMore || FALLBACK_URL,
|
accountExportLearnMore: linksConfigs.accountExportLearnMore || FALLBACK_URL,
|
||||||
walletLearnMore: linksConfigs.walletLearnMore || FALLBACK_URL,
|
walletLearnMore: linksConfigs.walletLearnMore || FALLBACK_URL,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ const ChaosLabsIcon: React.FC = () => {
|
|||||||
fill={fills[1]}
|
fill={fills[1]}
|
||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
fillRule="evenodd"
|
fill-rule="evenodd"
|
||||||
clipRule="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"
|
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]}
|
fill={fills[1]}
|
||||||
/>
|
/>
|
||||||
@@ -50,8 +50,8 @@ const ChaosLabsIcon: React.FC = () => {
|
|||||||
fill={fills[1]}
|
fill={fills[1]}
|
||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
fillRule="evenodd"
|
fill-rule="evenodd"
|
||||||
clipRule="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"
|
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]}
|
fill={fills[1]}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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 |
@@ -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
@@ -1,3 +1,4 @@
|
|||||||
|
import ChaosLabsIcon from './chaos-labs';
|
||||||
export { default as AddressConnectorIcon } from './address-connector.svg';
|
export { default as AddressConnectorIcon } from './address-connector.svg';
|
||||||
export { default as ArrowIcon } from './arrow.svg';
|
export { default as ArrowIcon } from './arrow.svg';
|
||||||
export { default as Bar3Icon } from './bar3.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 CoinsIcon } from './coins.svg';
|
||||||
export { default as CommentIcon } from './comment.svg';
|
export { default as CommentIcon } from './comment.svg';
|
||||||
export { default as CopyIcon } from './copy.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 DepositIcon } from './deposit.svg';
|
||||||
export { default as DepthChartIcon } from './depth-chart.svg';
|
export { default as DepthChartIcon } from './depth-chart.svg';
|
||||||
export { default as DiscordIcon } from './discord.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 FundingChartIcon } from './funding-chart.svg';
|
||||||
export { default as GearIcon } from './gear.svg';
|
export { default as GearIcon } from './gear.svg';
|
||||||
export { default as GiftboxIcon } from './giftbox.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 HelpCircleIcon } from './help-circle.svg';
|
||||||
export { default as HideIcon } from './hide.svg';
|
export { default as HideIcon } from './hide.svg';
|
||||||
export { default as HistoryIcon } from './history.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 SunIcon } from './sun.svg';
|
||||||
export { default as TerminalIcon } from './terminal.svg';
|
export { default as TerminalIcon } from './terminal.svg';
|
||||||
export { default as TogglesMenuIcon } from './toggles-menu.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 TradeIcon } from './trade.svg';
|
||||||
export { default as TransferIcon } from './transfer.svg';
|
export { default as TransferIcon } from './transfer.svg';
|
||||||
export { default as TriangleIcon } from './triangle.svg';
|
export { default as TriangleIcon } from './triangle.svg';
|
||||||
|
|||||||
@@ -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 |
@@ -30,7 +30,6 @@ import { OrderDetailsDialog } from '@/views/dialogs/DetailsDialog/OrderDetailsDi
|
|||||||
import { FillDetailsDialog } from '@/views/dialogs/DetailsDialog/FillDetailsDialog';
|
import { FillDetailsDialog } from '@/views/dialogs/DetailsDialog/FillDetailsDialog';
|
||||||
import { NewMarketMessageDetailsDialog } from '@/views/dialogs/NewMarketMessageDetailsDialog';
|
import { NewMarketMessageDetailsDialog } from '@/views/dialogs/NewMarketMessageDetailsDialog';
|
||||||
import { NewMarketAgreementDialog } from '@/views/dialogs/NewMarketAgreementDialog';
|
import { NewMarketAgreementDialog } from '@/views/dialogs/NewMarketAgreementDialog';
|
||||||
import { ExternalNavStrideDialog } from '@/views/dialogs/ExternalNavStrideDialog';
|
|
||||||
|
|
||||||
export const DialogManager = () => {
|
export const DialogManager = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@@ -60,7 +59,6 @@ export const DialogManager = () => {
|
|||||||
[DialogTypes.Help]: <HelpDialog {...modalProps} />,
|
[DialogTypes.Help]: <HelpDialog {...modalProps} />,
|
||||||
[DialogTypes.ExternalNavKeplr]: <ExternalNavKeplrDialog {...modalProps} />,
|
[DialogTypes.ExternalNavKeplr]: <ExternalNavKeplrDialog {...modalProps} />,
|
||||||
[DialogTypes.ExternalLink]: <ExternalLinkDialog {...modalProps} />,
|
[DialogTypes.ExternalLink]: <ExternalLinkDialog {...modalProps} />,
|
||||||
[DialogTypes.ExternalNavStride]: <ExternalNavStrideDialog {...modalProps} />,
|
|
||||||
[DialogTypes.MnemonicExport]: <MnemonicExportDialog {...modalProps} />,
|
[DialogTypes.MnemonicExport]: <MnemonicExportDialog {...modalProps} />,
|
||||||
[DialogTypes.MobileSignIn]: <MobileSignInDialog {...modalProps} />,
|
[DialogTypes.MobileSignIn]: <MobileSignInDialog {...modalProps} />,
|
||||||
[DialogTypes.Onboarding]: <OnboardingDialog {...modalProps} />,
|
[DialogTypes.Onboarding]: <OnboardingDialog {...modalProps} />,
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { OrderSide } from '@dydxprotocol/v4-client-js';
|
|
||||||
|
|
||||||
import { Candle, TradingViewBar, TradingViewSymbol } from '@/constants/candles';
|
import { Candle, TradingViewBar, TradingViewSymbol } from '@/constants/candles';
|
||||||
|
|
||||||
import { AppTheme, type AppColorMode } from '@/state/configs';
|
import type { AppTheme, AppColorMode } from '@/state/configs';
|
||||||
|
|
||||||
import { Themes } from '@/styles/themes';
|
import { Themes } from '@/styles/themes';
|
||||||
|
|
||||||
@@ -49,30 +47,6 @@ export const getHistorySlice = ({
|
|||||||
return bars.filter(({ time }) => time >= fromMs);
|
return bars.filter(({ time }) => time >= fromMs);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getOrderLineColors = ({
|
|
||||||
appTheme,
|
|
||||||
appColorMode,
|
|
||||||
side,
|
|
||||||
}: {
|
|
||||||
appTheme: AppTheme;
|
|
||||||
appColorMode: AppColorMode;
|
|
||||||
side: OrderSide;
|
|
||||||
}) => {
|
|
||||||
const theme = Themes[appTheme][appColorMode];
|
|
||||||
const orderColor = {
|
|
||||||
[OrderSide.BUY]: theme.positive,
|
|
||||||
[OrderSide.SELL]: theme.negative,
|
|
||||||
}[side];
|
|
||||||
|
|
||||||
return {
|
|
||||||
orderColor,
|
|
||||||
borderColor: theme.borderDefault,
|
|
||||||
backgroundColor: theme.layer1,
|
|
||||||
textColor: theme.textTertiary,
|
|
||||||
textButtonColor: theme.textButton,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getWidgetOverrides = ({
|
export const getWidgetOverrides = ({
|
||||||
appTheme,
|
appTheme,
|
||||||
appColorMode,
|
appColorMode,
|
||||||
@@ -83,7 +57,6 @@ export const getWidgetOverrides = ({
|
|||||||
const theme = Themes[appTheme][appColorMode];
|
const theme = Themes[appTheme][appColorMode];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
theme: appTheme === AppTheme.Dark ? 'dark' : AppTheme.Light ? 'light' : '',
|
|
||||||
overrides: {
|
overrides: {
|
||||||
'paneProperties.background': theme.layer2,
|
'paneProperties.background': theme.layer2,
|
||||||
'paneProperties.horzGridProperties.color': theme.layer3,
|
'paneProperties.horzGridProperties.color': theme.layer3,
|
||||||
|
|||||||
+18
-45
@@ -4,15 +4,9 @@ import { useDispatch, useSelector } from 'react-redux';
|
|||||||
import { useEnsName } from 'wagmi';
|
import { useEnsName } from 'wagmi';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { TransferType } from '@/constants/abacus';
|
|
||||||
import { OnboardingState } from '@/constants/account';
|
|
||||||
import { ButtonSize } from '@/constants/buttons';
|
import { ButtonSize } from '@/constants/buttons';
|
||||||
import { DialogTypes } from '@/constants/dialogs';
|
import { TransferType } from '@/constants/abacus';
|
||||||
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 { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
import { Details } from '@/components/Details';
|
import { Details } from '@/components/Details';
|
||||||
@@ -22,6 +16,13 @@ import { IconButton, type IconButtonProps } from '@/components/IconButton';
|
|||||||
import { Panel } from '@/components/Panel';
|
import { Panel } from '@/components/Panel';
|
||||||
import { Toolbar } from '@/components/Toolbar';
|
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 {
|
import {
|
||||||
getHistoricalTradingRewardsForCurrentWeek,
|
getHistoricalTradingRewardsForCurrentWeek,
|
||||||
getOnboardingState,
|
getOnboardingState,
|
||||||
@@ -31,12 +32,10 @@ import { openDialog } from '@/state/dialogs';
|
|||||||
import { isTruthy } from '@/lib/isTruthy';
|
import { isTruthy } from '@/lib/isTruthy';
|
||||||
import { truncateAddress } from '@/lib/wallet';
|
import { truncateAddress } from '@/lib/wallet';
|
||||||
|
|
||||||
import { DYDXBalancePanel } from './token/rewards/DYDXBalancePanel';
|
import { DYDXBalancePanel } from './rewards/DYDXBalancePanel';
|
||||||
import { MigratePanel } from './token/rewards/MigratePanel';
|
import { MigratePanel } from './rewards/MigratePanel';
|
||||||
import { GovernancePanel } from './token/rewards/GovernancePanel';
|
import { GovernancePanel } from './rewards/GovernancePanel';
|
||||||
import { StakingPanel } from './token/staking/StakingPanel';
|
import { StakingPanel } from './rewards/StakingPanel';
|
||||||
import { StrideStakingPanel } from './token/staking/StrideStakingPanel';
|
|
||||||
import { NewMarketsPanel } from './token/rewards/NewMarketsPanel';
|
|
||||||
|
|
||||||
const ENS_CHAIN_ID = 1; // Ethereum
|
const ENS_CHAIN_ID = 1; // Ethereum
|
||||||
|
|
||||||
@@ -237,9 +236,7 @@ const Profile = () => {
|
|||||||
</Styled.HistoryPanel>
|
</Styled.HistoryPanel>
|
||||||
|
|
||||||
<Styled.GovernancePanel />
|
<Styled.GovernancePanel />
|
||||||
<Styled.NewMarketsPanel />
|
|
||||||
<Styled.StakingPanel />
|
<Styled.StakingPanel />
|
||||||
<Styled.StrideStakingPanel />
|
|
||||||
</Styled.MobileProfileLayout>
|
</Styled.MobileProfileLayout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -252,12 +249,11 @@ Styled.MobileProfileLayout = styled.div`
|
|||||||
${layoutMixins.contentContainerPage}
|
${layoutMixins.contentContainerPage}
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
padding: 1.25rem 0.9rem;
|
padding: 1.25rem 0.9rem;
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
|
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
'header header'
|
'header header'
|
||||||
'actions actions'
|
'actions actions'
|
||||||
@@ -266,23 +262,8 @@ Styled.MobileProfileLayout = styled.div`
|
|||||||
'balance balance'
|
'balance balance'
|
||||||
'rewards fees'
|
'rewards fees'
|
||||||
'history history'
|
'history history'
|
||||||
'governance newMarkets'
|
'governance governance'
|
||||||
'keplr stride';
|
'staking staking';
|
||||||
|
|
||||||
@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';
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Header = styled.header`
|
Styled.Header = styled.header`
|
||||||
@@ -354,7 +335,7 @@ Styled.ActionButton = styled(IconButton)<{ iconName?: IconName }>`
|
|||||||
${({ iconName }) =>
|
${({ iconName }) =>
|
||||||
iconName === IconName.Close
|
iconName === IconName.Close
|
||||||
? css`
|
? css`
|
||||||
--button-textColor: var(--color-red);
|
--button-textColor: var(--color-error);
|
||||||
--button-icon-size: 0.75em;
|
--button-icon-size: 0.75em;
|
||||||
`
|
`
|
||||||
: iconName === IconName.Transfer &&
|
: iconName === IconName.Transfer &&
|
||||||
@@ -450,13 +431,5 @@ Styled.GovernancePanel = styled(GovernancePanel)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.StakingPanel = styled(StakingPanel)`
|
Styled.StakingPanel = styled(StakingPanel)`
|
||||||
grid-area: keplr;
|
grid-area: staking;
|
||||||
`;
|
|
||||||
|
|
||||||
Styled.NewMarketsPanel = styled(NewMarketsPanel)`
|
|
||||||
grid-area: newMarkets;
|
|
||||||
`;
|
|
||||||
|
|
||||||
Styled.StrideStakingPanel = styled(StrideStakingPanel)`
|
|
||||||
grid-area: stride;
|
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -45,8 +45,7 @@ export default () => {
|
|||||||
const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {};
|
const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {};
|
||||||
const { nativeTokenBalance } = useAccountBalance();
|
const { nativeTokenBalance } = useAccountBalance();
|
||||||
|
|
||||||
const { numTotalPositions, numTotalOpenOrders } =
|
const { numTotalPositions, numTotalOpenOrders } = useSelector(getTradeInfoNumbers, shallowEqual) || {};
|
||||||
useSelector(getTradeInfoNumbers, shallowEqual) || {};
|
|
||||||
const numPositions = shortenNumberForDisplay(numTotalPositions);
|
const numPositions = shortenNumberForDisplay(numTotalPositions);
|
||||||
const numOrders = shortenNumberForDisplay(numTotalOpenOrders);
|
const numOrders = shortenNumberForDisplay(numTotalOpenOrders);
|
||||||
|
|
||||||
@@ -120,43 +119,30 @@ export default () => {
|
|||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
value: PortfolioRoute.Overview,
|
value: PortfolioRoute.Overview,
|
||||||
slotBefore: (
|
slotBefore: <Styled.Icon iconName={IconName.Overview} />,
|
||||||
<Styled.IconContainer>
|
|
||||||
<Icon iconName={IconName.Overview} />
|
|
||||||
</Styled.IconContainer>
|
|
||||||
),
|
|
||||||
label: stringGetter({ key: STRING_KEYS.OVERVIEW }),
|
label: stringGetter({ key: STRING_KEYS.OVERVIEW }),
|
||||||
href: PortfolioRoute.Overview,
|
href: PortfolioRoute.Overview,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: PortfolioRoute.Positions,
|
value: PortfolioRoute.Positions,
|
||||||
slotBefore: (
|
slotBefore: <Styled.Icon iconName={IconName.Positions} />,
|
||||||
<Styled.IconContainer>
|
|
||||||
<Icon iconName={IconName.Positions} />
|
|
||||||
</Styled.IconContainer>
|
|
||||||
),
|
|
||||||
label: (
|
label: (
|
||||||
<>
|
<>
|
||||||
{stringGetter({ key: STRING_KEYS.POSITIONS })}
|
{stringGetter({ key: STRING_KEYS.POSITIONS })}
|
||||||
{numPositions &&
|
{numPositions > 0 && (
|
||||||
(typeof numPositions === 'string' || numPositions > 0) && (
|
<Tag type={TagType.Number}> {numPositions} </Tag>
|
||||||
<Tag type={TagType.Number}> {numPositions} </Tag>
|
)}
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
href: PortfolioRoute.Positions,
|
href: PortfolioRoute.Positions,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: PortfolioRoute.Orders,
|
value: PortfolioRoute.Orders,
|
||||||
slotBefore: (
|
slotBefore: <Styled.Icon iconName={IconName.OrderPending} />,
|
||||||
<Styled.IconContainer>
|
|
||||||
<Icon iconName={IconName.OrderPending} />
|
|
||||||
</Styled.IconContainer>
|
|
||||||
),
|
|
||||||
label: (
|
label: (
|
||||||
<>
|
<>
|
||||||
{stringGetter({ key: STRING_KEYS.ORDERS })}
|
{stringGetter({ key: STRING_KEYS.ORDERS })}
|
||||||
{numOrders && (typeof numOrders === 'string' || numOrders > 0) && (
|
{numOrders > 0 && (
|
||||||
<Tag type={TagType.Number}> {numOrders} </Tag>
|
<Tag type={TagType.Number}> {numOrders} </Tag>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
@@ -165,21 +151,13 @@ export default () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: PortfolioRoute.Fees,
|
value: PortfolioRoute.Fees,
|
||||||
slotBefore: (
|
slotBefore: <Styled.Icon iconName={IconName.Calculator} />,
|
||||||
<Styled.IconContainer>
|
|
||||||
<Icon iconName={IconName.Calculator} />
|
|
||||||
</Styled.IconContainer>
|
|
||||||
),
|
|
||||||
label: stringGetter({ key: STRING_KEYS.FEES }),
|
label: stringGetter({ key: STRING_KEYS.FEES }),
|
||||||
href: PortfolioRoute.Fees,
|
href: PortfolioRoute.Fees,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: PortfolioRoute.History,
|
value: PortfolioRoute.History,
|
||||||
slotBefore: (
|
slotBefore: <Styled.Icon iconName={IconName.History} />,
|
||||||
<Styled.IconContainer>
|
|
||||||
<Icon iconName={IconName.History} />
|
|
||||||
</Styled.IconContainer>
|
|
||||||
),
|
|
||||||
label: stringGetter({ key: STRING_KEYS.HISTORY }),
|
label: stringGetter({ key: STRING_KEYS.HISTORY }),
|
||||||
href: PortfolioRoute.History,
|
href: PortfolioRoute.History,
|
||||||
},
|
},
|
||||||
@@ -254,14 +232,16 @@ Styled.NavigationMenu = styled(NavigationMenu)`
|
|||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.IconContainer = styled.div`
|
Styled.Icon = styled(Icon)`
|
||||||
width: 1.5rem;
|
--icon-backgroundColor: var(--color-layer-4);
|
||||||
height: 1.5rem;
|
|
||||||
font-size: 0.75rem;
|
width: 1em;
|
||||||
display: flex;
|
height: 1em;
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
margin-left: -0.25em;
|
||||||
background-color: var(--color-layer-4);
|
|
||||||
|
box-sizing: content-box;
|
||||||
|
background-color: var(--icon-backgroundColor);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin-left: -0.25rem;
|
padding: 0.25em;
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -14,14 +14,13 @@ import { Link } from '@/components/Link';
|
|||||||
|
|
||||||
import { openDialog } from '@/state/dialogs';
|
import { openDialog } from '@/state/dialogs';
|
||||||
|
|
||||||
export const GovernancePanel = ({ className }: { className?: string }) => {
|
export const GovernancePanel = () => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { governanceLearnMore } = useURLConfigs();
|
const { governanceLearnMore } = useURLConfigs();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Panel
|
<Panel
|
||||||
className={className}
|
|
||||||
slotHeaderContent={
|
slotHeaderContent={
|
||||||
<Styled.Title>{stringGetter({ key: STRING_KEYS.GOVERNANCE })}</Styled.Title>
|
<Styled.Title>{stringGetter({ key: STRING_KEYS.GOVERNANCE })}</Styled.Title>
|
||||||
}
|
}
|
||||||
@@ -73,4 +72,4 @@ Styled.Title = styled.h3`
|
|||||||
font: var(--font-medium-book);
|
font: var(--font-medium-book);
|
||||||
color: var(--color-text-2);
|
color: var(--color-text-2);
|
||||||
margin-bottom: -1rem;
|
margin-bottom: -1rem;
|
||||||
`;
|
`;
|
||||||
+3
-7
@@ -28,7 +28,7 @@ import { log } from '@/lib/telemetry';
|
|||||||
|
|
||||||
const SEASON_NUMBER = 2;
|
const SEASON_NUMBER = 2;
|
||||||
|
|
||||||
export const LaunchIncentivesPanel = ({ className }: { className?: string }) => {
|
export const LaunchIncentivesPanel = () => {
|
||||||
const { isNotTablet } = useBreakpoints();
|
const { isNotTablet } = useBreakpoints();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
@@ -37,15 +37,11 @@ export const LaunchIncentivesPanel = ({ className }: { className?: string }) =>
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return isNotTablet ? (
|
return isNotTablet ? (
|
||||||
<Styled.Panel
|
<Styled.Panel slotHeader={<LaunchIncentivesTitle />} slotRight={<EstimatedRewards />}>
|
||||||
className={className}
|
|
||||||
slotHeader={<LaunchIncentivesTitle />}
|
|
||||||
slotRight={<EstimatedRewards />}
|
|
||||||
>
|
|
||||||
<LaunchIncentivesContent />
|
<LaunchIncentivesContent />
|
||||||
</Styled.Panel>
|
</Styled.Panel>
|
||||||
) : (
|
) : (
|
||||||
<Styled.Panel className={className}>
|
<Styled.Panel>
|
||||||
<Styled.Column>
|
<Styled.Column>
|
||||||
<EstimatedRewards />
|
<EstimatedRewards />
|
||||||
<LaunchIncentivesTitle />
|
<LaunchIncentivesTitle />
|
||||||
@@ -19,22 +19,21 @@ import { Tag } from '@/components/Tag';
|
|||||||
import { MustBigNumber } from '@/lib/numbers';
|
import { MustBigNumber } from '@/lib/numbers';
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
export const NewMarketsPanel = ({ className }: { className?: string }) => {
|
export const NewMarketsPanel = () => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { hasPotentialMarketsData } = usePotentialMarkets();
|
const { hasPotentialMarketsData } = usePotentialMarkets();
|
||||||
const { chainTokenDecimals, chainTokenLabel } = useTokenConfigs();
|
const { chainTokenDecimals, chainTokenLabel } = useTokenConfigs();
|
||||||
const { newMarketProposal } = useGovernanceVariables();
|
const { newMarketProposal } = useGovernanceVariables();
|
||||||
const initialDepositAmountDecimals = isMainnet ? 0 : 11;
|
|
||||||
const initialDepositAmountBN = MustBigNumber(newMarketProposal.initialDepositAmount).div(
|
const initialDepositAmountBN = MustBigNumber(newMarketProposal.initialDepositAmount).div(
|
||||||
Number(`1e${chainTokenDecimals}`)
|
Number(`1e${chainTokenDecimals}`)
|
||||||
);
|
);
|
||||||
|
const initialDepositAmountDecimals = isMainnet ? 0 : chainTokenDecimals;
|
||||||
|
|
||||||
if (!hasPotentialMarketsData) return null;
|
if (!hasPotentialMarketsData) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Panel
|
<Panel
|
||||||
className={className}
|
|
||||||
slotHeaderContent={
|
slotHeaderContent={
|
||||||
<Styled.Title>
|
<Styled.Title>
|
||||||
{stringGetter({ key: STRING_KEYS.ADD_A_MARKET })}
|
{stringGetter({ key: STRING_KEYS.ADD_A_MARKET })}
|
||||||
@@ -10,8 +10,6 @@ import { breakpoints } from '@/styles';
|
|||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
import { BackButton } from '@/components/BackButton';
|
import { BackButton } from '@/components/BackButton';
|
||||||
import { DetachedSection } from '@/components/ContentSection';
|
|
||||||
import { ContentSectionHeader } from '@/components/ContentSectionHeader';
|
|
||||||
|
|
||||||
import { testFlags } from '@/lib/testFlags';
|
import { testFlags } from '@/lib/testFlags';
|
||||||
|
|
||||||
@@ -21,6 +19,9 @@ import { MigratePanel } from './MigratePanel';
|
|||||||
import { RewardsHelpPanel } from './RewardsHelpPanel';
|
import { RewardsHelpPanel } from './RewardsHelpPanel';
|
||||||
import { TradingRewardsSummaryPanel } from './TradingRewardsSummaryPanel';
|
import { TradingRewardsSummaryPanel } from './TradingRewardsSummaryPanel';
|
||||||
import { RewardHistoryPanel } from './RewardHistoryPanel';
|
import { RewardHistoryPanel } from './RewardHistoryPanel';
|
||||||
|
import { GovernancePanel } from './GovernancePanel';
|
||||||
|
import { StakingPanel } from './StakingPanel';
|
||||||
|
import { NewMarketsPanel } from './NewMarketsPanel';
|
||||||
|
|
||||||
const RewardsPage = () => {
|
const RewardsPage = () => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
@@ -28,45 +29,46 @@ const RewardsPage = () => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<Styled.Page>
|
||||||
{isTablet && (
|
{isTablet && (
|
||||||
<ContentSectionHeader
|
<Styled.MobileHeader>
|
||||||
title={stringGetter({ key: STRING_KEYS.TRADING_REWARDS })}
|
<BackButton onClick={() => navigate(AppRoute.Profile)} />
|
||||||
slotLeft={<BackButton onClick={() => navigate(AppRoute.Profile)} />}
|
{stringGetter({ key: STRING_KEYS.TRADING_REWARDS })}
|
||||||
/>
|
</Styled.MobileHeader>
|
||||||
)}
|
)}
|
||||||
<DetachedSection>
|
<Styled.GridLayout
|
||||||
<Styled.GridLayout
|
showTradingRewards={testFlags.showTradingRewards}
|
||||||
showTradingRewards={testFlags.showTradingRewards}
|
showMigratePanel={import.meta.env.VITE_V3_TOKEN_ADDRESS && isNotTablet}
|
||||||
showMigratePanel={import.meta.env.VITE_V3_TOKEN_ADDRESS && isNotTablet}
|
>
|
||||||
>
|
{import.meta.env.VITE_V3_TOKEN_ADDRESS && isNotTablet && <Styled.MigratePanel />}
|
||||||
{import.meta.env.VITE_V3_TOKEN_ADDRESS && isNotTablet && <Styled.MigratePanel />}
|
|
||||||
|
|
||||||
{isTablet ? (
|
{isTablet ? (
|
||||||
|
<Styled.LaunchIncentivesPanel />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<Styled.LaunchIncentivesPanel />
|
<Styled.LaunchIncentivesPanel />
|
||||||
) : (
|
<Styled.DYDXBalancePanel />
|
||||||
<>
|
</>
|
||||||
<Styled.LaunchIncentivesPanel />
|
)}
|
||||||
<Styled.DYDXBalancePanel />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{testFlags.showTradingRewards && (
|
{testFlags.showTradingRewards && (
|
||||||
<Styled.TradingRewardsColumn>
|
<Styled.TradingRewardsColumn>
|
||||||
<TradingRewardsSummaryPanel />
|
<TradingRewardsSummaryPanel />
|
||||||
{isTablet && <RewardsHelpPanel />}
|
{isTablet && <RewardsHelpPanel />}
|
||||||
<RewardHistoryPanel />
|
<RewardHistoryPanel />
|
||||||
</Styled.TradingRewardsColumn>
|
</Styled.TradingRewardsColumn>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isNotTablet && (
|
{isNotTablet && (
|
||||||
<Styled.OtherColumn showTradingRewards={testFlags.showTradingRewards}>
|
<Styled.OtherColumn showTradingRewards={testFlags.showTradingRewards}>
|
||||||
<RewardsHelpPanel />
|
<NewMarketsPanel />
|
||||||
</Styled.OtherColumn>
|
<GovernancePanel />
|
||||||
)}
|
<StakingPanel />
|
||||||
</Styled.GridLayout>
|
<RewardsHelpPanel />
|
||||||
</DetachedSection>
|
</Styled.OtherColumn>
|
||||||
</div>
|
)}
|
||||||
|
</Styled.GridLayout>
|
||||||
|
</Styled.Page>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -74,6 +76,27 @@ export default RewardsPage;
|
|||||||
|
|
||||||
const Styled: Record<string, AnyStyledComponent> = {};
|
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`
|
Styled.MobileHeader = styled.header`
|
||||||
${layoutMixins.contentSectionDetachedScrollable}
|
${layoutMixins.contentSectionDetachedScrollable}
|
||||||
${layoutMixins.stickyHeader}
|
${layoutMixins.stickyHeader}
|
||||||
@@ -90,7 +113,6 @@ Styled.GridLayout = styled.div<{ showTradingRewards?: boolean; showMigratePanel?
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 2fr 1fr;
|
grid-template-columns: 2fr 1fr;
|
||||||
gap: var(--gap);
|
gap: var(--gap);
|
||||||
max-width: 80rem;
|
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
gap: var(--gap);
|
gap: var(--gap);
|
||||||
@@ -101,39 +123,24 @@ Styled.GridLayout = styled.div<{ showTradingRewards?: boolean; showMigratePanel?
|
|||||||
? css`
|
? css`
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
'migrate migrate'
|
'migrate migrate'
|
||||||
'incentives incentives'
|
'incentives balance'
|
||||||
'balance balance'
|
|
||||||
'rewards other';
|
'rewards other';
|
||||||
`
|
`
|
||||||
: showTradingRewards
|
: showTradingRewards
|
||||||
? css`
|
? css`
|
||||||
grid-template-areas:
|
grid-template-areas: 'incentives balance' 'rewards other';
|
||||||
'incentives balance'
|
|
||||||
'rewards other';
|
|
||||||
`
|
`
|
||||||
: showMigratePanel
|
: showMigratePanel
|
||||||
? css`
|
? css`
|
||||||
grid-template-areas:
|
grid-template-areas: 'migrate migrate' 'incentives balance' 'other other';
|
||||||
'migrate migrate'
|
|
||||||
'incentives incentives'
|
|
||||||
'balance balance'
|
|
||||||
'other other';
|
|
||||||
`
|
`
|
||||||
: css`
|
: css`
|
||||||
grid-template-areas:
|
grid-template-areas: 'incentives balance' 'other other';
|
||||||
'incentives balance'
|
|
||||||
'other other';
|
|
||||||
`};
|
`};
|
||||||
|
|
||||||
@media ${breakpoints.notTablet} {
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media ${breakpoints.tablet} {
|
@media ${breakpoints.tablet} {
|
||||||
--gap: 1rem;
|
--gap: 1rem;
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
width: calc(100vw - 2rem);
|
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
${({ showTradingRewards }) =>
|
${({ showTradingRewards }) =>
|
||||||
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 styled, { AnyStyledComponent } from 'styled-components';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
||||||
|
import { ButtonAction, ButtonSize } from '@/constants/buttons';
|
||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
import { DialogTypes } from '@/constants/dialogs';
|
import { DialogTypes } from '@/constants/dialogs';
|
||||||
|
|
||||||
@@ -13,19 +14,22 @@ import { Link } from '@/components/Link';
|
|||||||
|
|
||||||
import { openDialog } from '@/state/dialogs';
|
import { openDialog } from '@/state/dialogs';
|
||||||
|
|
||||||
export const StakingPanel = ({ className }: { className?: string }) => {
|
export const StakingPanel = () => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { stakingLearnMore } = useURLConfigs();
|
const { stakingLearnMore } = useURLConfigs();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Styled.Panel
|
<Panel
|
||||||
className={className}
|
slotHeaderContent={<Styled.Title>{stringGetter({ key: STRING_KEYS.STAKING })}</Styled.Title>}
|
||||||
slotHeaderContent={
|
slotRight={
|
||||||
<Styled.Header>
|
<Styled.Arrow>
|
||||||
<Styled.Title>Stake with Keplr</Styled.Title>
|
<Styled.IconButton
|
||||||
<Styled.Img src="/third-party/keplr.png" alt={stringGetter({ key: STRING_KEYS.KEPLR })} />
|
action={ButtonAction.Base}
|
||||||
</Styled.Header>
|
iconName={IconName.Arrow}
|
||||||
|
size={ButtonSize.Small}
|
||||||
|
/>
|
||||||
|
</Styled.Arrow>
|
||||||
}
|
}
|
||||||
onClick={() => dispatch(openDialog({ type: DialogTypes.ExternalNavKeplr }))}
|
onClick={() => dispatch(openDialog({ type: DialogTypes.ExternalNavKeplr }))}
|
||||||
>
|
>
|
||||||
@@ -35,40 +39,12 @@ export const StakingPanel = ({ className }: { className?: string }) => {
|
|||||||
{stringGetter({ key: STRING_KEYS.LEARN_MORE })} →
|
{stringGetter({ key: STRING_KEYS.LEARN_MORE })} →
|
||||||
</Link>
|
</Link>
|
||||||
</Styled.Description>
|
</Styled.Description>
|
||||||
</Styled.Panel>
|
</Panel>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Styled: Record<string, AnyStyledComponent> = {};
|
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`
|
Styled.Description = styled.div`
|
||||||
color: var(--color-text-0);
|
color: var(--color-text-0);
|
||||||
--link-color: var(--color-text-1);
|
--link-color: var(--color-text-1);
|
||||||
@@ -85,3 +61,13 @@ Styled.IconButton = styled(IconButton)`
|
|||||||
color: var(--color-text-0);
|
color: var(--color-text-0);
|
||||||
--color-border: var(--color-layer-6);
|
--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;
|
||||||
|
`;
|
||||||
+2
-5
@@ -3,8 +3,8 @@ import styled, { AnyStyledComponent } from 'styled-components';
|
|||||||
import { shallowEqual, useSelector } from 'react-redux';
|
import { shallowEqual, useSelector } from 'react-redux';
|
||||||
|
|
||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
import { useStringGetter, useTokenConfigs } from '@/hooks';
|
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
import { useStringGetter, useTokenConfigs } from '@/hooks';
|
||||||
|
|
||||||
import { AssetIcon } from '@/components/AssetIcon';
|
import { AssetIcon } from '@/components/AssetIcon';
|
||||||
import { Details } from '@/components/Details';
|
import { Details } from '@/components/Details';
|
||||||
@@ -18,10 +18,7 @@ import abacusStateManager from '@/lib/abacus';
|
|||||||
export const TradingRewardsSummaryPanel = () => {
|
export const TradingRewardsSummaryPanel = () => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const { chainTokenLabel } = useTokenConfigs();
|
const { chainTokenLabel } = useTokenConfigs();
|
||||||
const currentWeekTradingReward = useSelector(
|
const currentWeekTradingReward = useSelector(getHistoricalTradingRewardsForCurrentWeek, shallowEqual);
|
||||||
getHistoricalTradingRewardsForCurrentWeek,
|
|
||||||
shallowEqual
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
abacusStateManager.refreshHistoricalTradingRewards();
|
abacusStateManager.refreshHistoricalTradingRewards();
|
||||||
@@ -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="Participate in the ecosystem by voting on Governance proposals or submitting your own."
|
|
||||||
/>
|
|
||||||
</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);
|
|
||||||
`;
|
|
||||||
@@ -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: 'Staking Rewards', // 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;
|
|
||||||
`;
|
|
||||||
@@ -1,67 +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 { StakingPanel } from './StakingPanel';
|
|
||||||
import { StrideStakingPanel } from './StrideStakingPanel';
|
|
||||||
import { DYDXBalancePanel } from '../rewards/DYDXBalancePanel';
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<DetachedSection>
|
|
||||||
<Styled.HeaderSection>
|
|
||||||
<ContentSectionHeader
|
|
||||||
title="Staking Rewards"
|
|
||||||
subtitle="Stake to earn APR. Unstaking can take up to 30 days."
|
|
||||||
/>
|
|
||||||
</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,94 +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>
|
|
||||||
Liquid Stake with 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>
|
|
||||||
{`Stake your ${chainTokenLabel} tokens for st${chainTokenLabel} which you can deploy around the ecosystem.`}
|
|
||||||
<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);
|
|
||||||
`;
|
|
||||||
@@ -3,7 +3,7 @@ import { useSelector, shallowEqual } from 'react-redux';
|
|||||||
import styled, { AnyStyledComponent } from 'styled-components';
|
import styled, { AnyStyledComponent } from 'styled-components';
|
||||||
|
|
||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
import { ORDER_TYPE_STRINGS } from '@/constants/trade';
|
import { TRADE_TYPE_STRINGS } from '@/constants/trade';
|
||||||
|
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ export const TradeDialogTrigger = () => {
|
|||||||
<Styled.TradeSummary>
|
<Styled.TradeSummary>
|
||||||
<Styled.TradeType>
|
<Styled.TradeType>
|
||||||
<span>
|
<span>
|
||||||
{stringGetter({ key: ORDER_TYPE_STRINGS[selectedTradeType].orderTypeKey })}
|
{stringGetter({ key: TRADE_TYPE_STRINGS[selectedTradeType].tradeTypeKey })}
|
||||||
</span>
|
</span>
|
||||||
<OrderSideTag size={TagSize.Medium} orderSide={selectedOrderSide} />
|
<OrderSideTag size={TagSize.Medium} orderSide={selectedOrderSide} />
|
||||||
</Styled.TradeType>
|
</Styled.TradeType>
|
||||||
|
|||||||
@@ -2,10 +2,6 @@ import { createGlobalStyle } from 'styled-components';
|
|||||||
|
|
||||||
export const GlobalStyle = createGlobalStyle`
|
export const GlobalStyle = createGlobalStyle`
|
||||||
:root {
|
:root {
|
||||||
--color-white: ${({ theme }) => theme.white};
|
|
||||||
--color-green: ${({ theme }) => theme.green};
|
|
||||||
--color-red: ${({ theme }) => theme.red};
|
|
||||||
|
|
||||||
--color-layer-0: ${({ theme }) => theme.layer0};
|
--color-layer-0: ${({ theme }) => theme.layer0};
|
||||||
--color-layer-1: ${({ theme }) => theme.layer1};
|
--color-layer-1: ${({ theme }) => theme.layer1};
|
||||||
--color-layer-2: ${({ theme }) => theme.layer2};
|
--color-layer-2: ${({ theme }) => theme.layer2};
|
||||||
|
|||||||
+3
-12
@@ -4,10 +4,6 @@ import { BrightnessFilterToken, ColorToken, OpacityToken } from '@/constants/sty
|
|||||||
import { generateFadedColorVariant } from '@/lib/styles';
|
import { generateFadedColorVariant } from '@/lib/styles';
|
||||||
|
|
||||||
const ClassicThemeBase: ThemeColorBase = {
|
const ClassicThemeBase: ThemeColorBase = {
|
||||||
white: ColorToken.White,
|
|
||||||
green: ColorToken.Green1,
|
|
||||||
red: ColorToken.Red2,
|
|
||||||
|
|
||||||
layer0: ColorToken.GrayBlue7,
|
layer0: ColorToken.GrayBlue7,
|
||||||
layer1: ColorToken.GrayBlue6,
|
layer1: ColorToken.GrayBlue6,
|
||||||
layer2: ColorToken.GrayBlue5,
|
layer2: ColorToken.GrayBlue5,
|
||||||
@@ -55,6 +51,7 @@ const ClassicThemeBase: ThemeColorBase = {
|
|||||||
|
|
||||||
inputBackground: ColorToken.GrayBlue3,
|
inputBackground: ColorToken.GrayBlue3,
|
||||||
popoverBackground: generateFadedColorVariant(ColorToken.GrayBlue4, OpacityToken.Opacity90),
|
popoverBackground: generateFadedColorVariant(ColorToken.GrayBlue4, OpacityToken.Opacity90),
|
||||||
|
switchThumbActiveBackground: ColorToken.White,
|
||||||
toggleBackground: ColorToken.GrayBlue3,
|
toggleBackground: ColorToken.GrayBlue3,
|
||||||
tooltipBackground: generateFadedColorVariant(ColorToken.GrayBlue3, OpacityToken.Opacity66),
|
tooltipBackground: generateFadedColorVariant(ColorToken.GrayBlue3, OpacityToken.Opacity66),
|
||||||
|
|
||||||
@@ -64,10 +61,6 @@ const ClassicThemeBase: ThemeColorBase = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const DarkThemeBase: ThemeColorBase = {
|
const DarkThemeBase: ThemeColorBase = {
|
||||||
white: ColorToken.White,
|
|
||||||
green: ColorToken.Green0,
|
|
||||||
red: ColorToken.Red0,
|
|
||||||
|
|
||||||
layer0: ColorToken.Black,
|
layer0: ColorToken.Black,
|
||||||
layer1: ColorToken.DarkGray11,
|
layer1: ColorToken.DarkGray11,
|
||||||
layer2: ColorToken.DarkGray13,
|
layer2: ColorToken.DarkGray13,
|
||||||
@@ -115,6 +108,7 @@ const DarkThemeBase: ThemeColorBase = {
|
|||||||
|
|
||||||
inputBackground: ColorToken.DarkGray6,
|
inputBackground: ColorToken.DarkGray6,
|
||||||
popoverBackground: generateFadedColorVariant(ColorToken.DarkGray8, OpacityToken.Opacity90),
|
popoverBackground: generateFadedColorVariant(ColorToken.DarkGray8, OpacityToken.Opacity90),
|
||||||
|
switchThumbActiveBackground: ColorToken.White,
|
||||||
toggleBackground: ColorToken.DarkGray6,
|
toggleBackground: ColorToken.DarkGray6,
|
||||||
tooltipBackground: generateFadedColorVariant(ColorToken.DarkGray6, OpacityToken.Opacity66),
|
tooltipBackground: generateFadedColorVariant(ColorToken.DarkGray6, OpacityToken.Opacity66),
|
||||||
|
|
||||||
@@ -124,10 +118,6 @@ const DarkThemeBase: ThemeColorBase = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const LightThemeBase: ThemeColorBase = {
|
const LightThemeBase: ThemeColorBase = {
|
||||||
white: ColorToken.White,
|
|
||||||
green: ColorToken.Green2,
|
|
||||||
red: ColorToken.Red1,
|
|
||||||
|
|
||||||
layer0: ColorToken.White,
|
layer0: ColorToken.White,
|
||||||
layer1: ColorToken.LightGray6,
|
layer1: ColorToken.LightGray6,
|
||||||
layer2: ColorToken.White,
|
layer2: ColorToken.White,
|
||||||
@@ -175,6 +165,7 @@ const LightThemeBase: ThemeColorBase = {
|
|||||||
|
|
||||||
inputBackground: ColorToken.White,
|
inputBackground: ColorToken.White,
|
||||||
popoverBackground: generateFadedColorVariant(ColorToken.LightGray8, OpacityToken.Opacity90),
|
popoverBackground: generateFadedColorVariant(ColorToken.LightGray8, OpacityToken.Opacity90),
|
||||||
|
switchThumbActiveBackground: ColorToken.White,
|
||||||
toggleBackground: ColorToken.LightGray4,
|
toggleBackground: ColorToken.LightGray4,
|
||||||
tooltipBackground: generateFadedColorVariant(ColorToken.LightGray7, OpacityToken.Opacity66),
|
tooltipBackground: generateFadedColorVariant(ColorToken.LightGray7, OpacityToken.Opacity66),
|
||||||
|
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ export const AccountInfoConnectedState = () => {
|
|||||||
<WithTooltip tooltip={tooltip} stringParams={stringParams}>
|
<WithTooltip tooltip={tooltip} stringParams={stringParams}>
|
||||||
<Styled.WithUsage>
|
<Styled.WithUsage>
|
||||||
{label}
|
{label}
|
||||||
{hasError ? <Styled.CautionIcon iconName={IconName.CautionCircle} /> : slotRight}
|
{hasError ? <Styled.Icon iconName={IconName.CautionCircle} /> : slotRight}
|
||||||
</Styled.WithUsage>
|
</Styled.WithUsage>
|
||||||
</WithTooltip>
|
</WithTooltip>
|
||||||
),
|
),
|
||||||
@@ -230,7 +230,7 @@ Styled.CircleContainer = styled.div`
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.CautionIcon = styled(Icon)`
|
Styled.Icon = styled(Icon)`
|
||||||
color: var(--color-error);
|
color: var(--color-error);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -557,11 +557,11 @@ Styled.PositionTile = styled(PositionTile)``;
|
|||||||
|
|
||||||
Styled.ClosePositionButton = styled(Button)`
|
Styled.ClosePositionButton = styled(Button)`
|
||||||
--button-border: solid var(--border-width) var(--color-border-red);
|
--button-border: solid var(--border-width) var(--color-border-red);
|
||||||
--button-textColor: var(--color-red);
|
--button-textColor: var(--color-error);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.ClosePositionToggleButton = styled(ToggleButton)`
|
Styled.ClosePositionToggleButton = styled(ToggleButton)`
|
||||||
--button-border: solid var(--border-width) var(--color-border-red);
|
--button-border: solid var(--border-width) var(--color-border-red);
|
||||||
--button-toggle-off-textColor: var(--color-red);
|
--button-toggle-off-textColor: var(--color-error);
|
||||||
--button-toggle-on-textColor: var(--color-red);
|
--button-toggle-on-textColor: var(--color-error);
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -33,11 +33,9 @@ Styled.PositionInfoContainer = styled.div`
|
|||||||
|
|
||||||
PositionTileStory.args = {
|
PositionTileStory.args = {
|
||||||
currentSize: 0.2,
|
currentSize: 0.2,
|
||||||
notionalTotal: 1300,
|
oraclePrice: 1300,
|
||||||
postOrderSize: 0.2,
|
postOrderSize: 0.2,
|
||||||
stepSizeDecimals: 3,
|
stepSizeDecimals: 3,
|
||||||
symbol: 'ETH',
|
symbol: 'ETH',
|
||||||
tickSizeDecimals: 1,
|
tickSizeDecimals: 1,
|
||||||
isLoading: false,
|
|
||||||
showNarrowVariation: false,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,52 +1,28 @@
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
|
||||||
import styled, { type AnyStyledComponent, css } from 'styled-components';
|
import styled, { type AnyStyledComponent, css } from 'styled-components';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
|
||||||
import type {
|
import type { IChartingLibraryWidget, ResolutionString } from 'public/tradingview/charting_library';
|
||||||
IChartingLibraryWidget,
|
|
||||||
IOrderLineAdapter,
|
|
||||||
ResolutionString,
|
|
||||||
} from 'public/tradingview/charting_library';
|
|
||||||
|
|
||||||
import { AbacusOrderStatus } from '@/constants/abacus';
|
|
||||||
import { DEFAULT_RESOLUTION, RESOLUTION_CHART_CONFIGS } from '@/constants/candles';
|
|
||||||
import { DEFAULT_MARKETID } from '@/constants/markets';
|
import { DEFAULT_MARKETID } from '@/constants/markets';
|
||||||
import { type OrderType, ORDER_TYPE_STRINGS } from '@/constants/trade';
|
import { DEFAULT_RESOLUTION, RESOLUTION_CHART_CONFIGS } from '@/constants/candles';
|
||||||
|
|
||||||
import { useStringGetter } from '@/hooks';
|
|
||||||
import { useTradingView, useTradingViewTheme } from '@/hooks/tradingView';
|
import { useTradingView, useTradingViewTheme } from '@/hooks/tradingView';
|
||||||
|
|
||||||
import { LoadingSpace } from '@/components/Loading/LoadingSpinner';
|
import { LoadingSpace } from '@/components/Loading/LoadingSpinner';
|
||||||
|
|
||||||
import { getCurrentMarketOrders } from '@/state/accountSelectors';
|
|
||||||
import { getAppTheme, getAppColorMode } from '@/state/configsSelectors';
|
|
||||||
import { setTvChartResolution } from '@/state/perpetuals';
|
import { setTvChartResolution } from '@/state/perpetuals';
|
||||||
|
|
||||||
import { getCurrentMarketId, getSelectedResolutionForMarket } from '@/state/perpetualsSelectors';
|
import { getCurrentMarketId, getSelectedResolutionForMarket } from '@/state/perpetualsSelectors';
|
||||||
|
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
import { MustBigNumber } from '@/lib/numbers';
|
|
||||||
import { getOrderLineColors } from '@/lib/tradingView/utils';
|
|
||||||
|
|
||||||
type TvWidget = IChartingLibraryWidget & { _id?: string; _ready?: boolean };
|
type TvWidget = IChartingLibraryWidget & { _id?: string; _ready?: boolean };
|
||||||
|
|
||||||
let orderLines: Record<string, IOrderLineAdapter> = {};
|
|
||||||
|
|
||||||
export const TvChart = () => {
|
export const TvChart = () => {
|
||||||
const dispatch = useDispatch();
|
|
||||||
const stringGetter = useStringGetter();
|
|
||||||
|
|
||||||
const [isChartReady, setIsChartReady] = useState(false);
|
const [isChartReady, setIsChartReady] = useState(false);
|
||||||
const [showOrderLines, setShowOrderLines] = useState(false);
|
|
||||||
|
|
||||||
const displayButtonRef = useRef<HTMLElement | null>(null);
|
|
||||||
|
|
||||||
const appTheme = useSelector(getAppTheme);
|
|
||||||
const appColorMode = useSelector(getAppColorMode);
|
|
||||||
|
|
||||||
|
const dispatch = useDispatch();
|
||||||
const currentMarketId: string = useSelector(getCurrentMarketId) || DEFAULT_MARKETID;
|
const currentMarketId: string = useSelector(getCurrentMarketId) || DEFAULT_MARKETID;
|
||||||
const currentMarketOrders = useSelector(getCurrentMarketOrders, shallowEqual);
|
|
||||||
|
|
||||||
const selectedResolution: string =
|
const selectedResolution: string =
|
||||||
useSelector(getSelectedResolutionForMarket(currentMarketId)) || DEFAULT_RESOLUTION;
|
useSelector(getSelectedResolutionForMarket(currentMarketId)) || DEFAULT_RESOLUTION;
|
||||||
@@ -57,8 +33,8 @@ export const TvChart = () => {
|
|||||||
const chart = isWidgetReady ? tvWidget?.chart() : undefined;
|
const chart = isWidgetReady ? tvWidget?.chart() : undefined;
|
||||||
const chartResolution = chart?.resolution?.();
|
const chartResolution = chart?.resolution?.();
|
||||||
|
|
||||||
const { savedResolution } = useTradingView({ tvWidgetRef, displayButtonRef, setIsChartReady });
|
const { savedResolution } = useTradingView({ tvWidgetRef, setIsChartReady });
|
||||||
useTradingViewTheme({ tvWidget, isWidgetReady, orderLines });
|
useTradingViewTheme({ tvWidget, isWidgetReady });
|
||||||
|
|
||||||
const setVisibleRangeForResolution = ({ resolution }: { resolution: ResolutionString }) => {
|
const setVisibleRangeForResolution = ({ resolution }: { resolution: ResolutionString }) => {
|
||||||
// Different resolutions have different timeframes to display data efficiently.
|
// Different resolutions have different timeframes to display data efficiently.
|
||||||
@@ -73,9 +49,6 @@ export const TvChart = () => {
|
|||||||
tvWidget?.activeChart().setVisibleRange(newRange, { percentRightMargin: 10 });
|
tvWidget?.activeChart().setVisibleRange(newRange, { percentRightMargin: 10 });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Hook to handle changing chart resolution
|
|
||||||
*/
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (chartResolution) {
|
if (chartResolution) {
|
||||||
if (chartResolution !== selectedResolution) {
|
if (chartResolution !== selectedResolution) {
|
||||||
@@ -96,111 +69,6 @@ export const TvChart = () => {
|
|||||||
}
|
}
|
||||||
}, [currentMarketId, isWidgetReady]);
|
}, [currentMarketId, isWidgetReady]);
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Hook to handle order line toggle state
|
|
||||||
*/
|
|
||||||
useEffect(() => {
|
|
||||||
if (isChartReady && displayButtonRef && displayButtonRef.current) {
|
|
||||||
displayButtonRef.current.onclick = () => {
|
|
||||||
const newShowOrderLinesState = !showOrderLines;
|
|
||||||
if (newShowOrderLinesState) {
|
|
||||||
displayButtonRef.current?.classList?.add('order-lines-active');
|
|
||||||
} else {
|
|
||||||
displayButtonRef.current?.classList?.remove('order-lines-active');
|
|
||||||
}
|
|
||||||
setShowOrderLines(newShowOrderLinesState);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}, [isChartReady, showOrderLines]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Hook to handle drawing order lines
|
|
||||||
*/
|
|
||||||
useEffect(() => {
|
|
||||||
if (tvWidget && isChartReady) {
|
|
||||||
tvWidget.onChartReady(() => {
|
|
||||||
tvWidget.chart().dataReady(() => {
|
|
||||||
if (showOrderLines) {
|
|
||||||
drawOrderLines();
|
|
||||||
} else {
|
|
||||||
deleteOrderLines();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [isChartReady, showOrderLines, currentMarketOrders, currentMarketId]);
|
|
||||||
|
|
||||||
const drawOrderLines = () => {
|
|
||||||
if (!currentMarketOrders) return;
|
|
||||||
currentMarketOrders.forEach(
|
|
||||||
({
|
|
||||||
id,
|
|
||||||
type,
|
|
||||||
status,
|
|
||||||
side,
|
|
||||||
cancelReason,
|
|
||||||
remainingSize,
|
|
||||||
size,
|
|
||||||
triggerPrice,
|
|
||||||
price,
|
|
||||||
trailingPercent,
|
|
||||||
}) => {
|
|
||||||
const key = `${side.rawValue}-${id}`;
|
|
||||||
const quantity = (remainingSize ?? size).toString();
|
|
||||||
|
|
||||||
const orderType = type.rawValue as OrderType;
|
|
||||||
const orderLabel = stringGetter({
|
|
||||||
key: ORDER_TYPE_STRINGS[orderType].orderTypeKey,
|
|
||||||
});
|
|
||||||
const orderString = trailingPercent ? `${orderLabel} ${trailingPercent}%` : orderLabel;
|
|
||||||
|
|
||||||
const shouldShow =
|
|
||||||
!cancelReason &&
|
|
||||||
(status === AbacusOrderStatus.open || status === AbacusOrderStatus.untriggered);
|
|
||||||
|
|
||||||
const maybeOrderLine = key in orderLines ? orderLines[key] : null;
|
|
||||||
if (maybeOrderLine) {
|
|
||||||
if (!shouldShow) {
|
|
||||||
maybeOrderLine.remove();
|
|
||||||
delete orderLines[key];
|
|
||||||
return;
|
|
||||||
} else if (maybeOrderLine.getQuantity() !== quantity) {
|
|
||||||
maybeOrderLine.setQuantity(quantity);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (shouldShow) {
|
|
||||||
const { orderColor, borderColor, backgroundColor, textColor, textButtonColor } =
|
|
||||||
getOrderLineColors({ side: side.rawValue, appTheme, appColorMode });
|
|
||||||
|
|
||||||
const orderLine = tvWidget
|
|
||||||
?.chart()
|
|
||||||
.createOrderLine({ disableUndo: false })
|
|
||||||
.setPrice(MustBigNumber(triggerPrice ?? price).toNumber())
|
|
||||||
.setQuantity(quantity)
|
|
||||||
.setText(orderString)
|
|
||||||
.setLineColor(orderColor)
|
|
||||||
.setQuantityBackgroundColor(orderColor)
|
|
||||||
.setQuantityBorderColor(borderColor)
|
|
||||||
.setBodyBackgroundColor(backgroundColor)
|
|
||||||
.setBodyBorderColor(borderColor)
|
|
||||||
.setBodyTextColor(textColor)
|
|
||||||
.setQuantityTextColor(textButtonColor);
|
|
||||||
|
|
||||||
if (orderLine) {
|
|
||||||
orderLines[key] = orderLine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteOrderLines = () => {
|
|
||||||
Object.values(orderLines).forEach((line) => {
|
|
||||||
line.remove();
|
|
||||||
});
|
|
||||||
orderLines = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Styled.PriceChart isChartReady={isChartReady}>
|
<Styled.PriceChart isChartReady={isChartReady}>
|
||||||
{!isChartReady && <LoadingSpace id="tv-chart-loading" />}
|
{!isChartReady && <LoadingSpace id="tv-chart-loading" />}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export const DisplaySettingsDialog = ({ setIsOpen }: ElementProps) => {
|
|||||||
const sectionHeader = (heading: string) => {
|
const sectionHeader = (heading: string) => {
|
||||||
return (
|
return (
|
||||||
<Styled.Header>
|
<Styled.Header>
|
||||||
|
{heading}
|
||||||
{heading}
|
{heading}
|
||||||
<HorizontalSeparatorFiller />
|
<HorizontalSeparatorFiller />
|
||||||
</Styled.Header>
|
</Styled.Header>
|
||||||
@@ -286,10 +287,10 @@ Styled.ArrowIcon = styled(Icon)<{ direction: 'up' | 'down'; color: 'green' | 're
|
|||||||
${({ color }) =>
|
${({ color }) =>
|
||||||
({
|
({
|
||||||
['green']: css`
|
['green']: css`
|
||||||
color: var(--color-green);
|
color: var(--color-success);
|
||||||
`,
|
`,
|
||||||
['red']: css`
|
['red']: css`
|
||||||
color: var(--color-red);
|
color: var(--color-error);
|
||||||
`,
|
`,
|
||||||
}[color])}
|
}[color])}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import type { ReactNode } from 'react';
|
|
||||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||||
|
|
||||||
import { ButtonAction, ButtonType } from '@/constants/buttons';
|
import { ButtonAction, ButtonType } from '@/constants/buttons';
|
||||||
@@ -11,26 +10,18 @@ import { Dialog } from '@/components/Dialog';
|
|||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
type ElementProps = {
|
type ElementProps = {
|
||||||
buttonText?: ReactNode;
|
|
||||||
link: string;
|
link: string;
|
||||||
linkDescription?: string;
|
linkDescription?: string;
|
||||||
title?: ReactNode;
|
|
||||||
setIsOpen: (open: boolean) => void;
|
setIsOpen: (open: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ExternalLinkDialog = ({
|
export const ExternalLinkDialog = ({ setIsOpen, link, linkDescription }: ElementProps) => {
|
||||||
setIsOpen,
|
|
||||||
buttonText,
|
|
||||||
link,
|
|
||||||
linkDescription,
|
|
||||||
title,
|
|
||||||
}: ElementProps) => {
|
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
isOpen
|
isOpen
|
||||||
setIsOpen={setIsOpen}
|
setIsOpen={setIsOpen}
|
||||||
title={title ?? stringGetter({ key: STRING_KEYS.LEAVING_WEBSITE })}
|
title={stringGetter({ key: STRING_KEYS.LEAVING_WEBSITE })}
|
||||||
description={
|
description={
|
||||||
linkDescription ?? stringGetter({ key: STRING_KEYS.LEAVING_WEBSITE_DESCRIPTION })
|
linkDescription ?? stringGetter({ key: STRING_KEYS.LEAVING_WEBSITE_DESCRIPTION })
|
||||||
}
|
}
|
||||||
@@ -38,7 +29,7 @@ export const ExternalLinkDialog = ({
|
|||||||
<Styled.Content>
|
<Styled.Content>
|
||||||
<p>{stringGetter({ key: STRING_KEYS.LEAVING_WEBSITE_DISCLAIMER })}.</p>
|
<p>{stringGetter({ key: STRING_KEYS.LEAVING_WEBSITE_DISCLAIMER })}.</p>
|
||||||
<Button type={ButtonType.Link} action={ButtonAction.Primary} href={link}>
|
<Button type={ButtonType.Link} action={ButtonAction.Primary} href={link}>
|
||||||
{buttonText ?? stringGetter({ key: STRING_KEYS.CONTINUE })}
|
{stringGetter({ key: STRING_KEYS.CONTINUE })}
|
||||||
</Button>
|
</Button>
|
||||||
</Styled.Content>
|
</Styled.Content>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|||||||
@@ -1,137 +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>
|
|
||||||
Liquid Stake on Stride <Icon iconName={IconName.LinkOut} />
|
|
||||||
</Styled.Span>
|
|
||||||
),
|
|
||||||
link: strideZoneApp,
|
|
||||||
title: 'Liquid staking and leaving website',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
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>
|
|
||||||
<strong>{stringGetter({ key: STRING_KEYS.YES })}</strong>, Navigate to Stride Zone.
|
|
||||||
</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;
|
|
||||||
`;
|
|
||||||
@@ -155,7 +155,8 @@ Styled.CautionIconContainer = styled.div`
|
|||||||
content: '';
|
content: '';
|
||||||
width: 2.5rem;
|
width: 2.5rem;
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
background-color: var(--color-gradient-error);
|
background-color: var(--color-error);
|
||||||
|
opacity: 0.1;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ Styled.ReceiptArea = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Green = styled.span`
|
Styled.Green = styled.span`
|
||||||
color: var(--color-green);
|
color: var(--color-success);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.GreenCheckCircle = styled(GreenCheckCircle)`
|
Styled.GreenCheckCircle = styled(GreenCheckCircle)`
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import styled, { AnyStyledComponent, css } from 'styled-components';
|
|||||||
|
|
||||||
import { TradeInputField } from '@/constants/abacus';
|
import { TradeInputField } from '@/constants/abacus';
|
||||||
import { STRING_KEYS, StringKey } from '@/constants/localization';
|
import { STRING_KEYS, StringKey } from '@/constants/localization';
|
||||||
import { TradeTypes, ORDER_TYPE_STRINGS, MobilePlaceOrderSteps } from '@/constants/trade';
|
import { TradeTypes, TRADE_TYPE_STRINGS, MobilePlaceOrderSteps } from '@/constants/trade';
|
||||||
|
|
||||||
import { useBreakpoints, useStringGetter } from '@/hooks';
|
import { useBreakpoints, useStringGetter } from '@/hooks';
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { DialogTypes } from '@/constants/dialogs';
|
|||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
import { isMainnet } from '@/constants/networks';
|
import { isMainnet } from '@/constants/networks';
|
||||||
import { NumberSign, TOKEN_DECIMALS } from '@/constants/numbers';
|
import { NumberSign, TOKEN_DECIMALS } from '@/constants/numbers';
|
||||||
import type { PotentialMarketItem } from '@/constants/potentialMarkets';
|
import { LIQUIDITY_TIERS, type PotentialMarketItem } from '@/constants/potentialMarkets';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useAccountBalance,
|
useAccountBalance,
|
||||||
@@ -19,7 +19,6 @@ import {
|
|||||||
useStringGetter,
|
useStringGetter,
|
||||||
useSubaccount,
|
useSubaccount,
|
||||||
useTokenConfigs,
|
useTokenConfigs,
|
||||||
useURLConfigs,
|
|
||||||
} from '@/hooks';
|
} from '@/hooks';
|
||||||
import { usePotentialMarkets } from '@/hooks/usePotentialMarkets';
|
import { usePotentialMarkets } from '@/hooks/usePotentialMarkets';
|
||||||
|
|
||||||
@@ -32,7 +31,6 @@ import { DiffOutput } from '@/components/DiffOutput';
|
|||||||
import { FormInput } from '@/components/FormInput';
|
import { FormInput } from '@/components/FormInput';
|
||||||
import { Icon, IconName } from '@/components/Icon';
|
import { Icon, IconName } from '@/components/Icon';
|
||||||
import { InputType } from '@/components/Input';
|
import { InputType } from '@/components/Input';
|
||||||
import { Link } from '@/components/Link';
|
|
||||||
import { Output, OutputType } from '@/components/Output';
|
import { Output, OutputType } from '@/components/Output';
|
||||||
import { Tag } from '@/components/Tag';
|
import { Tag } from '@/components/Tag';
|
||||||
import { WithDetailsReceipt } from '@/components/WithDetailsReceipt';
|
import { WithDetailsReceipt } from '@/components/WithDetailsReceipt';
|
||||||
@@ -64,10 +62,9 @@ export const NewMarketPreviewStep = ({
|
|||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const { chainTokenDecimals, chainTokenLabel } = useTokenConfigs();
|
const { chainTokenDecimals, chainTokenLabel } = useTokenConfigs();
|
||||||
const [errorMessage, setErrorMessage] = useState();
|
const [errorMessage, setErrorMessage] = useState();
|
||||||
const { exchangeConfigs, liquidityTiers } = usePotentialMarkets();
|
const { exchangeConfigs } = usePotentialMarkets();
|
||||||
const { submitNewMarketProposal } = useSubaccount();
|
const { submitNewMarketProposal } = useSubaccount();
|
||||||
const { newMarketProposal } = useGovernanceVariables();
|
const { newMarketProposal } = useGovernanceVariables();
|
||||||
const { newMarketProposalLearnMore } = useURLConfigs();
|
|
||||||
const initialDepositAmountBN = MustBigNumber(newMarketProposal.initialDepositAmount).div(
|
const initialDepositAmountBN = MustBigNumber(newMarketProposal.initialDepositAmount).div(
|
||||||
Number(`1e${chainTokenDecimals}`)
|
Number(`1e${chainTokenDecimals}`)
|
||||||
);
|
);
|
||||||
@@ -76,7 +73,7 @@ export const NewMarketPreviewStep = ({
|
|||||||
const [hasAcceptedTerms, setHasAcceptedTerms] = useState(false);
|
const [hasAcceptedTerms, setHasAcceptedTerms] = useState(false);
|
||||||
|
|
||||||
const { label, initialMarginFraction, maintenanceMarginFraction, impactNotional } =
|
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`;
|
const ticker = `${assetData.baseAsset}-USD`;
|
||||||
|
|
||||||
@@ -314,15 +311,10 @@ export const NewMarketPreviewStep = ({
|
|||||||
</Styled.ButtonRow>
|
</Styled.ButtonRow>
|
||||||
<Styled.Disclaimer>
|
<Styled.Disclaimer>
|
||||||
{stringGetter({
|
{stringGetter({
|
||||||
key: STRING_KEYS.PROPOSAL_DISCLAIMER_1,
|
key: STRING_KEYS.PROPOSAL_DISCLAIMER,
|
||||||
params: {
|
params: {
|
||||||
NUM_TOKENS_REQUIRED: initialDepositAmount,
|
NUM_TOKENS_REQUIRED: initialDepositAmount,
|
||||||
NATIVE_TOKEN_DENOM: chainTokenLabel,
|
NATIVE_TOKEN_DENOM: chainTokenLabel,
|
||||||
HERE: (
|
|
||||||
<Styled.Link href={newMarketProposalLearnMore}>
|
|
||||||
{stringGetter({ key: STRING_KEYS.HERE })}
|
|
||||||
</Styled.Link>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
</Styled.Disclaimer>
|
</Styled.Disclaimer>
|
||||||
@@ -402,8 +394,3 @@ Styled.ButtonRow = styled.div`
|
|||||||
Styled.Button = styled(Button)`
|
Styled.Button = styled(Button)`
|
||||||
--button-padding: 0;
|
--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 { TOKEN_DECIMALS } from '@/constants/numbers';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
LIQUIDITY_TIERS,
|
||||||
NUM_ORACLES_TO_QUALIFY_AS_SAFE,
|
NUM_ORACLES_TO_QUALIFY_AS_SAFE,
|
||||||
type PotentialMarketItem,
|
type PotentialMarketItem,
|
||||||
} from '@/constants/potentialMarkets';
|
} from '@/constants/potentialMarkets';
|
||||||
@@ -73,7 +74,7 @@ export const NewMarketSelectionStep = ({
|
|||||||
const { isMobile } = useBreakpoints();
|
const { isMobile } = useBreakpoints();
|
||||||
const marketIds = useSelector(getMarketIds, shallowEqual);
|
const marketIds = useSelector(getMarketIds, shallowEqual);
|
||||||
const { chainTokenDecimals, chainTokenLabel } = useTokenConfigs();
|
const { chainTokenDecimals, chainTokenLabel } = useTokenConfigs();
|
||||||
const { potentialMarkets, exchangeConfigs, liquidityTiers } = usePotentialMarkets();
|
const { potentialMarkets, exchangeConfigs } = usePotentialMarkets();
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const { newMarketProposal } = useGovernanceVariables();
|
const { newMarketProposal } = useGovernanceVariables();
|
||||||
const initialDepositAmountBN = MustBigNumber(newMarketProposal.initialDepositAmount).div(
|
const initialDepositAmountBN = MustBigNumber(newMarketProposal.initialDepositAmount).div(
|
||||||
@@ -165,7 +166,7 @@ export const NewMarketSelectionStep = ({
|
|||||||
{assetToAdd?.assetName ?? assetToAdd.baseAsset} <Tag>{assetToAdd?.baseAsset}-USD</Tag>
|
{assetToAdd?.assetName ?? assetToAdd.baseAsset} <Tag>{assetToAdd?.baseAsset}-USD</Tag>
|
||||||
</Styled.SelectedAsset>
|
</Styled.SelectedAsset>
|
||||||
) : (
|
) : (
|
||||||
`${stringGetter({ key: STRING_KEYS.EG })} "BTC-USD"`
|
'e.g. "BTC-USD"'
|
||||||
)}
|
)}
|
||||||
</SearchSelectMenu>
|
</SearchSelectMenu>
|
||||||
{assetToAdd && (
|
{assetToAdd && (
|
||||||
@@ -209,9 +210,9 @@ export const NewMarketSelectionStep = ({
|
|||||||
</Styled.ButtonRow>
|
</Styled.ButtonRow>
|
||||||
</Styled.Header>
|
</Styled.Header>
|
||||||
|
|
||||||
{Object.keys(liquidityTiers).map((tier) => {
|
{Object.keys(LIQUIDITY_TIERS).map((tier) => {
|
||||||
const { maintenanceMarginFraction, impactNotional, label, initialMarginFraction } =
|
const { maintenanceMarginFraction, impactNotional, label, initialMarginFraction } =
|
||||||
liquidityTiers[tier as unknown as keyof typeof liquidityTiers];
|
LIQUIDITY_TIERS[tier as unknown as keyof typeof LIQUIDITY_TIERS];
|
||||||
return (
|
return (
|
||||||
<Styled.LiquidityTierRadioButton
|
<Styled.LiquidityTierRadioButton
|
||||||
key={tier}
|
key={tier}
|
||||||
@@ -233,7 +234,7 @@ export const NewMarketSelectionStep = ({
|
|||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
key: 'imf',
|
key: 'imf',
|
||||||
label: stringGetter({ key: STRING_KEYS.INITIAL_MARGIN_FRACTION_SHORT }),
|
label: 'IMF',
|
||||||
tooltip: 'initial-margin-fraction',
|
tooltip: 'initial-margin-fraction',
|
||||||
value: (
|
value: (
|
||||||
<Output
|
<Output
|
||||||
@@ -245,9 +246,7 @@ export const NewMarketSelectionStep = ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'mmf',
|
key: 'mmf',
|
||||||
label: stringGetter({
|
label: 'MMF',
|
||||||
key: STRING_KEYS.MAINTENANCE_MARGIN_FRACTION_SHORT,
|
|
||||||
}),
|
|
||||||
tooltip: 'maintenance-margin-fraction',
|
tooltip: 'maintenance-margin-fraction',
|
||||||
value: (
|
value: (
|
||||||
<Output
|
<Output
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import type { TradeInputSummary } from '@/constants/abacus';
|
|||||||
import { ButtonAction, ButtonSize, ButtonType } from '@/constants/buttons';
|
import { ButtonAction, ButtonSize, ButtonType } from '@/constants/buttons';
|
||||||
import { DialogTypes } from '@/constants/dialogs';
|
import { DialogTypes } from '@/constants/dialogs';
|
||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
import { ORDER_TYPE_STRINGS, MobilePlaceOrderSteps } from '@/constants/trade';
|
import { TRADE_TYPE_STRINGS, MobilePlaceOrderSteps } from '@/constants/trade';
|
||||||
|
|
||||||
import { useStringGetter, useTokenConfigs } from '@/hooks';
|
import { useStringGetter, useTokenConfigs } from '@/hooks';
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ export const PlaceOrderButtonAndReceipt = ({
|
|||||||
ORDER: stringGetter({
|
ORDER: stringGetter({
|
||||||
key: isClosePosition
|
key: isClosePosition
|
||||||
? STRING_KEYS.CLOSE_ORDER
|
? STRING_KEYS.CLOSE_ORDER
|
||||||
: ORDER_TYPE_STRINGS[selectedTradeType].orderTypeKey,
|
: TRADE_TYPE_STRINGS[selectedTradeType].tradeTypeKey,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ export const TransferForm = ({
|
|||||||
label={
|
label={
|
||||||
<Styled.DestinationInputLabel>
|
<Styled.DestinationInputLabel>
|
||||||
{stringGetter({ key: STRING_KEYS.DESTINATION })}
|
{stringGetter({ key: STRING_KEYS.DESTINATION })}
|
||||||
{isAddressValid && <Styled.CheckIcon iconName={IconName.Check} />}
|
{isAddressValid && <Icon iconName={IconName.Check} />}
|
||||||
</Styled.DestinationInputLabel>
|
</Styled.DestinationInputLabel>
|
||||||
}
|
}
|
||||||
type={InputType.Text}
|
type={InputType.Text}
|
||||||
@@ -439,10 +439,10 @@ Styled.InlineRow = styled.span`
|
|||||||
|
|
||||||
Styled.DestinationInputLabel = styled.span`
|
Styled.DestinationInputLabel = styled.span`
|
||||||
${layoutMixins.inlineRow}
|
${layoutMixins.inlineRow}
|
||||||
`;
|
|
||||||
|
|
||||||
Styled.CheckIcon = styled(Icon)`
|
svg {
|
||||||
color: var(--color-success);
|
color: var(--color-success);
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.AddressValidationAlertMessage = styled(AlertMessage)`
|
Styled.AddressValidationAlertMessage = styled(AlertMessage)`
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ElementType, memo } from 'react';
|
import { memo } from 'react';
|
||||||
import styled, { AnyStyledComponent, css } from 'styled-components';
|
import styled, { AnyStyledComponent, css } from 'styled-components';
|
||||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||||
import type { Dispatch } from '@reduxjs/toolkit';
|
import type { Dispatch } from '@reduxjs/toolkit';
|
||||||
@@ -106,7 +106,7 @@ export const AccountMenu = () => {
|
|||||||
{walletType && (
|
{walletType && (
|
||||||
<Styled.SourceIcon>
|
<Styled.SourceIcon>
|
||||||
<Styled.ConnectorIcon iconName={IconName.AddressConnector} />
|
<Styled.ConnectorIcon iconName={IconName.AddressConnector} />
|
||||||
<Icon iconComponent={wallets[walletType].icon as ElementType} />
|
<Icon iconComponent={wallets[walletType].icon} />
|
||||||
</Styled.SourceIcon>
|
</Styled.SourceIcon>
|
||||||
)}
|
)}
|
||||||
<Styled.Column>
|
<Styled.Column>
|
||||||
@@ -220,7 +220,7 @@ export const AccountMenu = () => {
|
|||||||
{onboardingState === OnboardingState.WalletConnected ? (
|
{onboardingState === OnboardingState.WalletConnected ? (
|
||||||
<Styled.WarningIcon iconName={IconName.Warning} />
|
<Styled.WarningIcon iconName={IconName.Warning} />
|
||||||
) : onboardingState === OnboardingState.AccountConnected ? (
|
) : onboardingState === OnboardingState.AccountConnected ? (
|
||||||
walletType && <Icon iconComponent={wallets[walletType].icon as ElementType} />
|
walletType && <Icon iconComponent={wallets[walletType].icon} />
|
||||||
) : null}
|
) : null}
|
||||||
{!isTablet && <Styled.Address>{truncateAddress(dydxAddress)}</Styled.Address>}
|
{!isTablet && <Styled.Address>{truncateAddress(dydxAddress)}</Styled.Address>}
|
||||||
</Styled.DropdownMenu>
|
</Styled.DropdownMenu>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
} from '@/constants/abacus';
|
} from '@/constants/abacus';
|
||||||
|
|
||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
import { ORDER_TYPE_STRINGS, TradeTypes } from '@/constants/trade';
|
import { TRADE_TYPE_STRINGS, TradeTypes } from '@/constants/trade';
|
||||||
import { useStringGetter } from '@/hooks';
|
import { useStringGetter } from '@/hooks';
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ export const TradeNotification = ({ isToast, data, notification }: TradeNotifica
|
|||||||
const { assetId } = marketData ?? {};
|
const { assetId } = marketData ?? {};
|
||||||
const orderType = ORDER_TYPE as KotlinIrEnumValues<typeof AbacusOrderType>;
|
const orderType = ORDER_TYPE as KotlinIrEnumValues<typeof AbacusOrderType>;
|
||||||
const tradeType = TRADE_TYPES[orderType];
|
const tradeType = TRADE_TYPES[orderType];
|
||||||
const titleKey = tradeType && ORDER_TYPE_STRINGS[tradeType]?.orderTypeKey;
|
const titleKey = tradeType && TRADE_TYPE_STRINGS[tradeType]?.tradeTypeKey;
|
||||||
const orderStatus = ORDER_STATUS as KotlinIrEnumValues<typeof AbacusOrderStatus>;
|
const orderStatus = ORDER_STATUS as KotlinIrEnumValues<typeof AbacusOrderStatus>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -82,6 +82,6 @@ Styled.ActionButton = styled(IconButton)`
|
|||||||
|
|
||||||
Styled.CancelButton = styled(Styled.ActionButton)`
|
Styled.CancelButton = styled(Styled.ActionButton)`
|
||||||
&:not(:disabled) {
|
&:not(:disabled) {
|
||||||
--button-textColor: var(--color-red);
|
--button-textColor: var(--color-error);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user