Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87731097b8 | ||
|
|
1e9209028e | ||
|
|
2861286bdb | ||
|
|
e93850484b |
+18
-9
@@ -5,29 +5,35 @@ import styled from 'styled-components';
|
||||
|
||||
import { store } from '@/state/_store';
|
||||
|
||||
import { GlobalStyle } from '@/styles/globalStyle';
|
||||
|
||||
import { SelectMenu, SelectItem } from '@/components/SelectMenu';
|
||||
|
||||
import { AppThemeProvider } from '@/hooks/useAppTheme';
|
||||
|
||||
import { AppTheme, setAppTheme } from '@/state/configs';
|
||||
import { setLocaleLoaded } from '@/state/localization';
|
||||
|
||||
import '@/index.css';
|
||||
import './ladle.css';
|
||||
|
||||
export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const [theme, setTheme] = useState('Default theme');
|
||||
const [theme, setTheme] = useState(AppTheme.Classic);
|
||||
|
||||
useEffect(() => {
|
||||
store.dispatch(setAppTheme(theme));
|
||||
switch (theme) {
|
||||
case 'Dark theme': {
|
||||
case AppTheme.Dark: {
|
||||
document?.documentElement?.classList.remove('theme-light');
|
||||
document?.documentElement?.classList.add('theme-dark');
|
||||
break;
|
||||
}
|
||||
case 'Light theme': {
|
||||
case AppTheme.Light: {
|
||||
document?.documentElement?.classList.remove('theme-dark');
|
||||
document?.documentElement?.classList.add('theme-light');
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
case AppTheme.Classic: {
|
||||
document?.documentElement?.classList.remove('theme-dark', 'theme-light');
|
||||
break;
|
||||
}
|
||||
@@ -48,15 +54,15 @@ export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children
|
||||
>
|
||||
{[
|
||||
{
|
||||
value: 'Default theme',
|
||||
value: AppTheme.Classic,
|
||||
label: 'Default theme',
|
||||
},
|
||||
{
|
||||
value: 'Dark theme',
|
||||
value: AppTheme.Dark,
|
||||
label: 'Dark theme',
|
||||
},
|
||||
{
|
||||
value: 'Light theme',
|
||||
value: AppTheme.Light,
|
||||
label: 'Light theme',
|
||||
},
|
||||
].map(({ value, label }) => (
|
||||
@@ -69,8 +75,11 @@ export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children
|
||||
</SelectMenu>
|
||||
</StoryHeader>
|
||||
<hr />
|
||||
<StoryContent>{children}</StoryContent>
|
||||
</Provider>
|
||||
<AppThemeProvider>
|
||||
<GlobalStyle />
|
||||
<StoryContent>{children}</StoryContent>
|
||||
</AppThemeProvider>
|
||||
</Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
if('serviceWorker' in navigator) navigator.serviceWorker.register('/dev-sw.js?dev-sw', { scope: '/', type: 'classic' })
|
||||
@@ -44,8 +44,6 @@
|
||||
"@dydxprotocol/v4-localization": "^1.1.11",
|
||||
"@ethersproject/providers": "^5.7.2",
|
||||
"@js-joda/core": "^5.5.3",
|
||||
"@privy-io/react-auth": "^1.53.1",
|
||||
"@privy-io/wagmi-connector": "^0.1.12",
|
||||
"@radix-ui/react-accordion": "^1.1.2",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-collapsible": "^1.0.3",
|
||||
@@ -153,7 +151,6 @@
|
||||
"url-polyfill": "^1.1.12",
|
||||
"util": "^0.12.5",
|
||||
"vite": "^4.3.9",
|
||||
"vite-plugin-pwa": "^0.17.4",
|
||||
"vite-plugin-svgr": "^3.2.0",
|
||||
"vitest": "^0.32.2",
|
||||
"w3name": "^1.0.8",
|
||||
|
||||
Generated
+46
-2708
File diff suppressed because it is too large
Load Diff
+41
-42
@@ -2,8 +2,6 @@ import { lazy, Suspense } from 'react';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
import styled, { AnyStyledComponent, css } from 'styled-components';
|
||||
import { WagmiConfig } from 'wagmi';
|
||||
import { PrivyProvider } from '@privy-io/react-auth';
|
||||
import { PrivyWagmiConnector } from '@privy-io/wagmi-connector';
|
||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||
import { GrazProvider } from 'graz';
|
||||
|
||||
@@ -18,6 +16,7 @@ import {
|
||||
} from '@/hooks';
|
||||
import { DydxProvider } from '@/hooks/useDydxClient';
|
||||
import { AccountsProvider } from '@/hooks/useAccounts';
|
||||
import { AppThemeProvider } from '@/hooks/useAppTheme';
|
||||
import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
|
||||
import { LocaleProvider } from '@/hooks/useLocaleSeparators';
|
||||
import { NotificationsProvider } from '@/hooks/useNotifications';
|
||||
@@ -34,9 +33,10 @@ import { NotificationsToastArea } from '@/layout/NotificationsToastArea';
|
||||
import { DialogManager } from '@/layout/DialogManager';
|
||||
import { GlobalCommandDialog } from '@/views/dialogs/GlobalCommandDialog';
|
||||
|
||||
import { config, privyConfig } from '@/lib/wagmi';
|
||||
import { config } from '@/lib/wagmi';
|
||||
|
||||
import { breakpoints } from '@/styles';
|
||||
import { GlobalStyle } from '@/styles/globalStyle';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
import { LoadingSpace } from './components/Loading/LoadingSpinner';
|
||||
|
||||
@@ -68,49 +68,52 @@ const Content = () => {
|
||||
const { chainTokenLabel } = useTokenConfigs();
|
||||
|
||||
return (
|
||||
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
|
||||
{isNotTablet && <HeaderDesktop />}
|
||||
<>
|
||||
<GlobalStyle />
|
||||
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
|
||||
{isNotTablet && <HeaderDesktop />}
|
||||
|
||||
<Styled.Main>
|
||||
<Suspense fallback={<LoadingSpace id="main" />}>
|
||||
<Routes>
|
||||
<Route path={AppRoute.Trade}>
|
||||
<Route path=":market" element={<TradePage />} />
|
||||
<Route path={AppRoute.Trade} element={<TradePage />} />
|
||||
</Route>
|
||||
<Styled.Main>
|
||||
<Suspense fallback={<LoadingSpace id="main" />}>
|
||||
<Routes>
|
||||
<Route path={AppRoute.Trade}>
|
||||
<Route path=":market" element={<TradePage />} />
|
||||
<Route path={AppRoute.Trade} element={<TradePage />} />
|
||||
</Route>
|
||||
|
||||
<Route path={AppRoute.Markets} element={<MarketsPage />} />
|
||||
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
|
||||
{isTablet && (
|
||||
<>
|
||||
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
||||
<Route path={AppRoute.Profile} element={<ProfilePage />} />
|
||||
<Route path={`${AppRoute.Settings}/*`} element={<SettingsPage />} />
|
||||
</>
|
||||
)}
|
||||
<Route path={AppRoute.Markets} element={<MarketsPage />} />
|
||||
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
|
||||
{isTablet && (
|
||||
<>
|
||||
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
||||
<Route path={AppRoute.Profile} element={<ProfilePage />} />
|
||||
<Route path={`${AppRoute.Settings}/*`} element={<SettingsPage />} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<Route element={<GuardedMobileRoute />}>
|
||||
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
|
||||
</Route>
|
||||
<Route element={<GuardedMobileRoute />}>
|
||||
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
|
||||
</Route>
|
||||
|
||||
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
|
||||
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
|
||||
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
|
||||
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
|
||||
|
||||
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</Styled.Main>
|
||||
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</Styled.Main>
|
||||
|
||||
{isTablet ? <FooterMobile /> : <FooterDesktop />}
|
||||
{isTablet ? <FooterMobile /> : <FooterDesktop />}
|
||||
|
||||
<Styled.NotificationsToastArea />
|
||||
<Styled.NotificationsToastArea />
|
||||
|
||||
<Styled.DialogArea ref={setDialogArea}>
|
||||
<DialogManager />
|
||||
</Styled.DialogArea>
|
||||
<Styled.DialogArea ref={setDialogArea}>
|
||||
<DialogManager />
|
||||
</Styled.DialogArea>
|
||||
|
||||
<GlobalCommandDialog />
|
||||
</Styled.Content>
|
||||
<GlobalCommandDialog />
|
||||
</Styled.Content>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -122,13 +125,8 @@ const wrapProvider = (Component: React.ComponentType<any>, props?: any) => {
|
||||
};
|
||||
|
||||
const providers = [
|
||||
wrapProvider(PrivyProvider, {
|
||||
appId: import.meta.env.VITE_PRIVY_APP_ID,
|
||||
config: privyConfig,
|
||||
}),
|
||||
wrapProvider(QueryClientProvider, { client: queryClient }),
|
||||
wrapProvider(GrazProvider),
|
||||
wrapProvider(PrivyWagmiConnector, { wagmiChainsConfig: config }),
|
||||
wrapProvider(WagmiConfig, { config }),
|
||||
wrapProvider(LocaleProvider),
|
||||
wrapProvider(RestrictionProvider),
|
||||
@@ -138,6 +136,7 @@ const providers = [
|
||||
wrapProvider(LocalNotificationsProvider),
|
||||
wrapProvider(NotificationsProvider),
|
||||
wrapProvider(DialogAreaProvider),
|
||||
wrapProvider(AppThemeProvider),
|
||||
];
|
||||
|
||||
const App = () => {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
|
||||
import { RiskLevels } from '@/constants/abacus';
|
||||
import { UsageColorFromRiskLevel } from '@/styles/colors';
|
||||
|
||||
import { Ring } from '@/components/Ring';
|
||||
|
||||
import { abacusHelper } from '@/lib/abacus';
|
||||
import { UsageColorFromRiskLevel } from '@/lib/styles';
|
||||
|
||||
type ElementProps = {
|
||||
value: number;
|
||||
|
||||
@@ -47,7 +47,7 @@ Styled.Root = styled(Root)`
|
||||
--switch-thumb-backgroundColor: var(--color-layer-6);
|
||||
|
||||
--switch-active-backgroundColor: var(--color-accent);
|
||||
--switch-active-thumb-backgroundColor: var(--color-white);
|
||||
--switch-active-thumb-backgroundColor: ${({ theme }) => theme.switchThumbActiveBackground};
|
||||
|
||||
position: relative;
|
||||
width: var(--switch-width);
|
||||
|
||||
@@ -2,9 +2,9 @@ import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
|
||||
import { type RiskLevels } from '@/constants/abacus';
|
||||
|
||||
import { UsageColorFromRiskLevel } from '@/styles/colors';
|
||||
|
||||
import { abacusHelper } from '@/lib/abacus';
|
||||
import { UsageColorFromRiskLevel } from '@/lib/styles';
|
||||
|
||||
type ElementProps = {
|
||||
value: number;
|
||||
};
|
||||
|
||||
@@ -110,12 +110,7 @@ Styled.Abbr = styled.abbr`
|
||||
|
||||
Styled.Content = styled(Content)`
|
||||
--tooltip-backgroundColor: var(--color-layer-4);
|
||||
--tooltip-backgroundColor: hsl(
|
||||
var(--layer-base-hue),
|
||||
var(--layer-base-saturation),
|
||||
calc(var(--layer-base-lightness) + 4%),
|
||||
0.66
|
||||
);
|
||||
--tooltip-backgroundColor: ${({ theme }) => theme.tooltipBackground};
|
||||
|
||||
${popoverMixins.popover}
|
||||
--popover-backgroundColor: var(--tooltip-backgroundColor);
|
||||
|
||||
@@ -27,12 +27,7 @@ Styled.TooltipContent = styled.aside<{ accentColor?: string }>`
|
||||
|
||||
${popoverMixins.popover}
|
||||
--popover-radius: 0.5rem;
|
||||
--popover-background-color: hsl(
|
||||
var(--layer-base-hue),
|
||||
var(--layer-base-saturation),
|
||||
calc(var(--layer-base-lightness)),
|
||||
0.9
|
||||
);
|
||||
--popover-background-color: ${({ theme }) => theme.popoverBackground};
|
||||
--popover-backdrop-filter: saturate(120%) blur(12px);
|
||||
|
||||
display: grid;
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
export enum ColorToken {
|
||||
Black = '#000000',
|
||||
White = '#FFFFFF',
|
||||
|
||||
LightGray0 = '#FAFAFA',
|
||||
LightGray1 = '#F7F8FA',
|
||||
LightGray2 = '#FAFAFD',
|
||||
LightGray3 = '#F5F5F5',
|
||||
LightGray4 = '#EDF0F2',
|
||||
LightGray5 = '#EDEDED',
|
||||
LightGray6 = '#E9ECEE',
|
||||
LightGray7 = '#E6E6E6',
|
||||
LightGray8 = '#DBDBDB',
|
||||
LightGray9 = '#D5DADF',
|
||||
LightGray10 = '#D1D9E0',
|
||||
|
||||
MediumGray0 = '#CACACE',
|
||||
MediumGray1 = '#C2CBD3',
|
||||
|
||||
DarkGray0 = '#888891',
|
||||
DarkGray1 = '#737373',
|
||||
DarkGray2 = '#56565C',
|
||||
DarkGray3 = '#4B4B4B',
|
||||
DarkGray4 = '#494950',
|
||||
DarkGray5 = '#3B3B3F',
|
||||
DarkGray6 = '#303033',
|
||||
DarkGray7 = '#313135',
|
||||
DarkGray8 = '#292929',
|
||||
DarkGray9 = '#23232F',
|
||||
DarkGray10 = '#212124',
|
||||
DarkGray11 = '#18181B',
|
||||
DarkGray12 = '#181818',
|
||||
DarkGray13 = '#0C0C0D',
|
||||
|
||||
GrayBlue0 = '#464659',
|
||||
GrayBlue1 = '#38384D',
|
||||
GrayBlue2 = '#303045',
|
||||
GrayBlue3 = '#29293D',
|
||||
GrayBlue4 = '#212131',
|
||||
GrayBlue5 = '#181825',
|
||||
GrayBlue6 = '#101018',
|
||||
GrayBlue7 = '#08080C',
|
||||
|
||||
GrayPurple0 = '#DFDADF',
|
||||
GrayPurple1 = '#C8C7D8',
|
||||
GrayPurple2 = '#807E98',
|
||||
|
||||
Purple0 = '#7774FF',
|
||||
Purple1 = '#6966FF',
|
||||
|
||||
Green0 = '#1AFFB9',
|
||||
Green1 = '#3ED9A4',
|
||||
Green2 = '#2CCC98',
|
||||
Green3 = '#3EB68A',
|
||||
|
||||
Yellow0 = '#FFCC48',
|
||||
Yellow1 = '#FFB647',
|
||||
|
||||
Red0 = '#FF5C5C',
|
||||
Red1 = '#E76565',
|
||||
Red2 = '#E45555',
|
||||
}
|
||||
|
||||
/** Maps opacity to corresponding hex value */
|
||||
export enum OpacityToken {
|
||||
Opacity16 = '29',
|
||||
Opacity20 = '33',
|
||||
Opacity66 = 'A8',
|
||||
Opacity90 = 'E6',
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
export type ThemeColors = LayerColors &
|
||||
BorderColors &
|
||||
TextColors &
|
||||
GradientColors &
|
||||
AccentColors &
|
||||
StatusColors &
|
||||
DirectionalColors &
|
||||
RiskColors &
|
||||
IconColors &
|
||||
ComponentColors;
|
||||
|
||||
type LayerColors = {
|
||||
layer0: string;
|
||||
layer1: string;
|
||||
layer2: string;
|
||||
layer3: string;
|
||||
layer4: string;
|
||||
layer5: string;
|
||||
layer6: string;
|
||||
layer7: string;
|
||||
};
|
||||
|
||||
type BorderColors = {
|
||||
borderDefault: string;
|
||||
borderDestructive: string;
|
||||
borderButton: string;
|
||||
};
|
||||
|
||||
type TextColors = {
|
||||
textPrimary: string;
|
||||
textSecondary: string;
|
||||
textTertiary: string;
|
||||
};
|
||||
|
||||
type GradientColors = {
|
||||
gradientBase0: string;
|
||||
gradientBase1: string;
|
||||
};
|
||||
|
||||
type AccentColors = {
|
||||
accent: string;
|
||||
accentFaded: string;
|
||||
favorite: string;
|
||||
};
|
||||
|
||||
type StatusColors = {
|
||||
success: string;
|
||||
warning: string;
|
||||
error: string;
|
||||
};
|
||||
|
||||
type DirectionalColors = {
|
||||
positive: string;
|
||||
negative: string;
|
||||
positiveFaded: string;
|
||||
negativeFaded: string;
|
||||
};
|
||||
|
||||
type RiskColors = {
|
||||
riskLow: string;
|
||||
riskMedium: string;
|
||||
riskHigh: string;
|
||||
};
|
||||
|
||||
type IconColors = {
|
||||
logoFill: string;
|
||||
profileYellow: string;
|
||||
profileRed: string;
|
||||
};
|
||||
|
||||
type ComponentColors = {
|
||||
inputBackground: string;
|
||||
popoverBackground: string;
|
||||
switchThumbActiveBackground: string;
|
||||
toggleBackground: string;
|
||||
tooltipBackground: string;
|
||||
};
|
||||
@@ -31,7 +31,6 @@ import { DydxNetwork, ENVIRONMENT_CONFIG_MAP } from './networks';
|
||||
export enum WalletConnectionType {
|
||||
CoinbaseWalletSdk = 'coinbaseWalletSdk',
|
||||
CosmosSigner = 'CosmosSigner',
|
||||
Privy = 'Privy',
|
||||
InjectedEip1193 = 'injectedEip1193',
|
||||
WalletConnect2 = 'walletConnect2',
|
||||
}
|
||||
@@ -69,9 +68,6 @@ export const walletConnectionTypes: Record<WalletConnectionType, WalletConnectio
|
||||
[WalletConnectionType.CosmosSigner]: {
|
||||
name: 'CosmosSigner',
|
||||
},
|
||||
[WalletConnectionType.Privy]: {
|
||||
name: 'Privy',
|
||||
},
|
||||
};
|
||||
|
||||
// Wallets
|
||||
@@ -94,7 +90,6 @@ export enum WalletType {
|
||||
WalletConnect2 = 'WALLETCONNECT_2',
|
||||
// TestWallet = 'TEST_WALLET',
|
||||
OtherWallet = 'OTHER_WALLET',
|
||||
Privy = 'PRIVY',
|
||||
}
|
||||
|
||||
const WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS = {
|
||||
@@ -248,12 +243,6 @@ export const wallets: Record<WalletType, WalletConfig> = {
|
||||
icon: KeplrIcon,
|
||||
connectionTypes: [WalletConnectionType.CosmosSigner],
|
||||
},
|
||||
[WalletType.Privy]: {
|
||||
type: WalletType.Privy,
|
||||
stringKey: STRING_KEYS.KEPLR,
|
||||
icon: GenericWalletIcon,
|
||||
connectionTypes: [WalletConnectionType.Privy],
|
||||
},
|
||||
};
|
||||
|
||||
// Injected EIP-1193 Providers
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useSelector } from 'react-redux';
|
||||
import type { IChartingLibraryWidget, ThemeName } from 'public/tradingview/charting_library';
|
||||
|
||||
import { AppTheme } from '@/state/configs';
|
||||
|
||||
import { getAppTheme } from '@/state/configsSelectors';
|
||||
|
||||
import { getWidgetOverrides } from '@/lib/tradingView/utils';
|
||||
@@ -29,7 +28,7 @@ export const useTradingViewTheme = ({
|
||||
tvWidget: (IChartingLibraryWidget & { _id?: string; _ready?: boolean }) | null;
|
||||
isWidgetReady?: boolean;
|
||||
}) => {
|
||||
const appTheme = useSelector(getAppTheme);
|
||||
const appTheme: AppTheme = useSelector(getAppTheme);
|
||||
|
||||
useEffect(() => {
|
||||
if (tvWidget && isWidgetReady) {
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
import { useCallback, useContext, createContext, useEffect, useState, useMemo } from 'react';
|
||||
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { AES, enc } from 'crypto-js';
|
||||
import { NOBLE_BECH32_PREFIX, LocalWallet, type Subaccount } from '@dydxprotocol/v4-client-js';
|
||||
|
||||
import { OnboardingGuard, OnboardingState, type EvmDerivedAddresses } from '@/constants/account';
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
import { LocalStorageKey, LOCAL_STORAGE_VERSIONS } from '@/constants/localStorage';
|
||||
import {
|
||||
DydxAddress,
|
||||
EvmAddress,
|
||||
PrivateInformation,
|
||||
WalletConnectionType,
|
||||
getSignTypedData,
|
||||
} from '@/constants/wallets';
|
||||
import { DydxAddress, EvmAddress, PrivateInformation } from '@/constants/wallets';
|
||||
|
||||
import { setOnboardingState, setOnboardingGuard } from '@/state/account';
|
||||
import { forceOpenDialog } from '@/state/dialogs';
|
||||
@@ -26,11 +20,6 @@ import { useLocalStorage } from './useLocalStorage';
|
||||
import { useRestrictions } from './useRestrictions';
|
||||
import { useWalletConnection } from './useWalletConnection';
|
||||
|
||||
import { useSignTypedData } from 'wagmi';
|
||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
import { usePrivy } from '@privy-io/react-auth';
|
||||
|
||||
const AccountsContext = createContext<ReturnType<typeof useAccountsContext> | undefined>(undefined);
|
||||
|
||||
AccountsContext.displayName = 'Accounts';
|
||||
@@ -164,7 +153,6 @@ const useAccountsContext = () => {
|
||||
|
||||
// dYdX wallet / onboarding state
|
||||
const [localDydxWallet, setLocalDydxWallet] = useState<LocalWallet>();
|
||||
const [localNobleWallet, setLocalNobleWallet] = useState<LocalWallet>();
|
||||
const [hdKey, setHdKey] = useState<PrivateInformation>();
|
||||
|
||||
const dydxAccounts = useMemo(() => localDydxWallet?.accounts, [localDydxWallet]);
|
||||
@@ -174,11 +162,6 @@ const useAccountsContext = () => {
|
||||
[localDydxWallet]
|
||||
);
|
||||
|
||||
const nobleAddress = useMemo(
|
||||
() => localNobleWallet?.address,
|
||||
[localNobleWallet]
|
||||
);
|
||||
|
||||
const setWalletFromEvmSignature = async (signature: string) => {
|
||||
const { wallet, mnemonic, privateKey, publicKey } = await getWalletFromEvmSignature({
|
||||
signature,
|
||||
@@ -193,20 +176,6 @@ const useAccountsContext = () => {
|
||||
}
|
||||
}, [evmAddress, dydxAddress]);
|
||||
|
||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||
|
||||
const chainId = Number(ENVIRONMENT_CONFIG_MAP[selectedNetwork].ethereumChainId);
|
||||
|
||||
const signTypedData = getSignTypedData(selectedNetwork);
|
||||
const { signTypedDataAsync } = useSignTypedData({
|
||||
...signTypedData,
|
||||
domain: {
|
||||
...signTypedData.domain,
|
||||
chainId,
|
||||
},
|
||||
});
|
||||
const { ready, authenticated } = usePrivy();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (connectedDydxAddress && signerGraz) {
|
||||
@@ -223,17 +192,7 @@ const useAccountsContext = () => {
|
||||
|
||||
const evmDerivedAccount = evmDerivedAddresses[evmAddress];
|
||||
|
||||
if (walletConnectionType === WalletConnectionType.Privy && authenticated && ready) {
|
||||
try {
|
||||
const signature = await signTypedDataAsync();
|
||||
|
||||
await setWalletFromEvmSignature(signature);
|
||||
dispatch(setOnboardingState(OnboardingState.AccountConnected));
|
||||
} catch (error) {
|
||||
log('useAccounts/decryptSignature', error);
|
||||
forgetEvmSignature();
|
||||
}
|
||||
} else if (evmDerivedAccount?.encryptedSignature) {
|
||||
if (evmDerivedAccount?.encryptedSignature) {
|
||||
try {
|
||||
const signature = decryptSignature(evmDerivedAccount.encryptedSignature);
|
||||
|
||||
@@ -252,15 +211,7 @@ const useAccountsContext = () => {
|
||||
dispatch(setOnboardingState(OnboardingState.Disconnected));
|
||||
}
|
||||
})();
|
||||
}, [
|
||||
evmAddress,
|
||||
evmDerivedAddresses,
|
||||
signerWagmi,
|
||||
connectedDydxAddress,
|
||||
signerGraz,
|
||||
authenticated,
|
||||
ready,
|
||||
]);
|
||||
}, [evmAddress, evmDerivedAddresses, signerWagmi, connectedDydxAddress, signerGraz]);
|
||||
|
||||
// abacus
|
||||
useEffect(() => {
|
||||
@@ -273,7 +224,6 @@ const useAccountsContext = () => {
|
||||
if (hdKey?.mnemonic) {
|
||||
const nobleWallet = await LocalWallet.fromMnemonic(hdKey.mnemonic, NOBLE_BECH32_PREFIX);
|
||||
abacusStateManager.setNobleWallet(nobleWallet);
|
||||
setLocalNobleWallet(nobleWallet);
|
||||
}
|
||||
};
|
||||
setNobleWallet();
|
||||
@@ -372,7 +322,6 @@ const useAccountsContext = () => {
|
||||
localDydxWallet,
|
||||
dydxAccounts,
|
||||
dydxAddress,
|
||||
nobleAddress,
|
||||
|
||||
// Onboarding state
|
||||
saveHasAcknowledgedTerms,
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { useSelector } from 'react-redux';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
|
||||
import { AppTheme } from '@/state/configs';
|
||||
import { getAppTheme } from '@/state/configsSelectors';
|
||||
|
||||
import { Themes } from '@/styles/themes';
|
||||
|
||||
export const AppThemeProvider = ({ ...props }) => {
|
||||
return <ThemeProvider theme={useAppThemeContext()} {...props} />
|
||||
};
|
||||
|
||||
export const useAppThemeContext = () => {
|
||||
const theme: AppTheme = useSelector(getAppTheme);
|
||||
return Themes[theme];
|
||||
}
|
||||
@@ -21,7 +21,6 @@ export const useDisplayedWallets = () => {
|
||||
// WalletType.BitKeep,
|
||||
// WalletType.Coin98,
|
||||
|
||||
WalletType.Privy,
|
||||
WalletType.OtherWallet,
|
||||
].filter(isTruthy);
|
||||
};
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import { useNetwork, useSwitchNetwork } from 'wagmi';
|
||||
import { useSwitchNetwork as useSwitchNetworkPrivy } from '@privy-io/wagmi-connector';
|
||||
import { WalletConnectionType } from '@/constants/wallets';
|
||||
|
||||
import { useWalletConnection } from './useWalletConnection';
|
||||
|
||||
export const useMatchingEvmNetwork = ({
|
||||
chainId,
|
||||
@@ -15,10 +11,7 @@ export const useMatchingEvmNetwork = ({
|
||||
onError?: (error: Error) => void;
|
||||
}) => {
|
||||
const { chain } = useNetwork();
|
||||
const { walletConnectionType } = useWalletConnection();
|
||||
const { isLoading, switchNetworkAsync } = useSwitchNetwork({ onError });
|
||||
const { isLoading: isLoadingPrivy, switchNetworkAsync: switchNetworkAsyncPrivy } =
|
||||
useSwitchNetworkPrivy({ onError });
|
||||
|
||||
// If chainId is not a number, we can assume it is a non EVM compatible chain
|
||||
const isMatchingNetwork = useMemo(
|
||||
@@ -28,11 +21,7 @@ export const useMatchingEvmNetwork = ({
|
||||
|
||||
const matchNetwork = useCallback(async () => {
|
||||
if (!isMatchingNetwork) {
|
||||
if (walletConnectionType === WalletConnectionType.Privy) {
|
||||
await switchNetworkAsyncPrivy?.(Number(chainId));
|
||||
} else {
|
||||
await switchNetworkAsync?.(Number(chainId));
|
||||
}
|
||||
await switchNetworkAsync?.(Number(chainId));
|
||||
}
|
||||
}, [chainId, chain]);
|
||||
|
||||
@@ -45,6 +34,6 @@ export const useMatchingEvmNetwork = ({
|
||||
return {
|
||||
isMatchingNetwork,
|
||||
matchNetwork,
|
||||
isSwitchingNetwork: isLoading || isLoadingPrivy,
|
||||
isSwitchingNetwork: isLoading,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useCallback, useEffect, useState, useMemo } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { usePrivy, useLogout } from '@privy-io/react-auth';
|
||||
|
||||
import { LocalStorageKey } from '@/constants/localStorage';
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
@@ -105,10 +104,8 @@ export const useWalletConnection = () => {
|
||||
[walletConnectConfig, walletType, walletConnectionType]
|
||||
);
|
||||
|
||||
const { connectAsync: connectWagmi } = useConnectWagmi({ connector: wagmiConnector });
|
||||
const { connectAsync: connectWagmi } = useConnectWagmi({ connector: wagmiConnector })
|
||||
const { suggestAndConnect: connectGraz } = useConnectGraz();
|
||||
const { login, ready, authenticated } = usePrivy();
|
||||
const { logout } = useLogout();
|
||||
|
||||
const connectWallet = useCallback(
|
||||
async ({ walletType }: { walletType: WalletType }) => {
|
||||
@@ -117,11 +114,6 @@ export const useWalletConnection = () => {
|
||||
try {
|
||||
if (!walletConnection) {
|
||||
throw new Error('Onboarding: No wallet connection found.');
|
||||
} else if (walletConnection.type === WalletConnectionType.Privy) {
|
||||
|
||||
if (!isConnectedWagmi && !authenticated && ready) {
|
||||
login();
|
||||
}
|
||||
} else if (walletConnection.type === WalletConnectionType.CosmosSigner) {
|
||||
const cosmosWalletType = {
|
||||
[WalletType.Keplr as string]: CosmosWalletType.KEPLR,
|
||||
@@ -164,7 +156,7 @@ export const useWalletConnection = () => {
|
||||
walletConnectionType: walletConnection.type,
|
||||
};
|
||||
},
|
||||
[isConnectedGraz, signerGraz, isConnectedWagmi, signerWagmi, login, ready, authenticated]
|
||||
[isConnectedGraz, signerGraz, isConnectedWagmi, signerWagmi]
|
||||
);
|
||||
|
||||
const disconnectWallet = useCallback(async () => {
|
||||
@@ -173,7 +165,6 @@ export const useWalletConnection = () => {
|
||||
|
||||
if (isConnectedWagmi) await disconnectWagmi();
|
||||
if (isConnectedGraz) await disconnectGraz();
|
||||
if (authenticated) await logout();
|
||||
}, [isConnectedGraz, isConnectedWagmi]);
|
||||
|
||||
// Wallet selection
|
||||
|
||||
+50
-43
@@ -1,45 +1,52 @@
|
||||
const LogoShortIcon: React.FC<{ id?: string }> = ({ id }: { id?: string }) => (
|
||||
<svg
|
||||
width="135"
|
||||
height="145"
|
||||
viewBox="0 0 135 145"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M100.986 0L0 144.988H31.0048L132.514 0H100.986Z" fill="white" />
|
||||
<path
|
||||
d="M34.2346 0L63.9475 42.7232L48.4451 66.0268L2.58386 0H34.2346Z"
|
||||
fill={`url(#${id ? `${id}_logo_gradient_0` : 'paint0_linear'})`}
|
||||
/>
|
||||
<path
|
||||
d="M103.995 145L71.0526 97.7455L86.555 75.0893L135 145H103.995Z"
|
||||
fill={`url(#${id ? `${id}_logo_gradient_1` : 'paint1_linear'})`}
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id={id ? `${id}_logo_gradient_0` : 'paint0_linear'}
|
||||
x1="27.1293"
|
||||
y1="9.0625"
|
||||
x2="69.773"
|
||||
y2="60.4324"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="white" />
|
||||
<stop offset="1" stopColor="white" stopOpacity="0.55" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id={id ? `${id}_logo_gradient_1` : 'paint1_linear'}
|
||||
x1="111.1"
|
||||
y1="133.996"
|
||||
x2="58.6959"
|
||||
y2="63.4999"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="#6966FF" />
|
||||
<stop offset="1" stopColor="#6966FF" stopOpacity="0.36" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
import { useAppThemeContext } from '@/hooks/useAppTheme';
|
||||
|
||||
const LogoShortIcon: React.FC<{ id?: string }> = ({ id }: { id?: string }) => {
|
||||
const theme = useAppThemeContext();
|
||||
const fill = theme.logoFill;
|
||||
|
||||
return (
|
||||
<svg
|
||||
width="135"
|
||||
height="145"
|
||||
viewBox="0 0 135 145"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M100.986 0L0 144.988H31.0048L132.514 0H100.986Z" fill={fill} />
|
||||
<path
|
||||
d="M34.2346 0L63.9475 42.7232L48.4451 66.0268L2.58386 0H34.2346Z"
|
||||
fill={`url(#${id ? `${id}_logo_gradient_0` : 'paint0_linear'})`}
|
||||
/>
|
||||
<path
|
||||
d="M103.995 145L71.0526 97.7455L86.555 75.0893L135 145H103.995Z"
|
||||
fill={`url(#${id ? `${id}_logo_gradient_1` : 'paint1_linear'})`}
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id={id ? `${id}_logo_gradient_0` : 'paint0_linear'}
|
||||
x1="27.1293"
|
||||
y1="9.0625"
|
||||
x2="69.773"
|
||||
y2="60.4324"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor={fill} />
|
||||
<stop offset="1" stopColor={fill} stopOpacity="0.55" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id={id ? `${id}_logo_gradient_1` : 'paint1_linear'}
|
||||
x1="111.1"
|
||||
y1="133.996"
|
||||
x2="58.6959"
|
||||
y2="63.4999"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="#6966FF" />
|
||||
<stop offset="1" stopColor="#6966FF" stopOpacity="0.36" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default LogoShortIcon;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
@import 'styles/fonts.css';
|
||||
@import 'styles/text.css';
|
||||
@import 'styles/colors.css';
|
||||
@import 'styles/animations.css';
|
||||
|
||||
:root {
|
||||
|
||||
@@ -56,6 +56,10 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
||||
this.store = undefined;
|
||||
}
|
||||
|
||||
get isNobleClientConnected(): boolean {
|
||||
return this.nobleClient?.isConnected ?? false;
|
||||
}
|
||||
|
||||
setStore(store: RootStore): void {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { css } from 'styled-components';
|
||||
|
||||
import { type RiskLevels } from '@/constants/abacus';
|
||||
|
||||
export const UsageColorFromRiskLevel = (riskLevel: RiskLevels) =>
|
||||
({
|
||||
low: css`
|
||||
color: var(--color-risk-low);
|
||||
`,
|
||||
medium: css`
|
||||
color: var(--color-risk-medium);
|
||||
`,
|
||||
high: css`
|
||||
color: var(--color-risk-high);
|
||||
`,
|
||||
}[riskLevel.name]);
|
||||
|
||||
export const generateFadedColorVariant = (colorHex: string, opacityHex: string) => {
|
||||
return `${colorHex}${opacityHex}`;
|
||||
};
|
||||
@@ -1,11 +1,9 @@
|
||||
import Color from 'color';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
import { Candle, TradingViewBar, TradingViewSymbol } from '@/constants/candles';
|
||||
import { Colors } from '@/styles/colors';
|
||||
|
||||
import { AppTheme } from '@/state/configs';
|
||||
|
||||
import { Themes } from '@/styles/themes';
|
||||
|
||||
export const mapCandle = ({
|
||||
startedAt,
|
||||
open,
|
||||
@@ -49,42 +47,42 @@ export const getHistorySlice = ({
|
||||
return bars.filter(({ time }) => time >= fromMs);
|
||||
};
|
||||
|
||||
export const getWidgetOverrides = (theme: AppTheme) => {
|
||||
const colors = Colors[theme];
|
||||
export const getWidgetOverrides = (appTheme: AppTheme) => {
|
||||
const theme = Themes[appTheme];
|
||||
|
||||
return {
|
||||
overrides: {
|
||||
'paneProperties.background': Color(colors.layer2).hex(),
|
||||
'paneProperties.horzGridProperties.color': Color(colors.layer3).hex(),
|
||||
'paneProperties.vertGridProperties.color': Color(colors.layer3).hex(),
|
||||
'paneProperties.background': theme.layer2,
|
||||
'paneProperties.horzGridProperties.color': theme.layer3,
|
||||
'paneProperties.vertGridProperties.color': theme.layer3,
|
||||
'paneProperties.crossHairProperties.style': 1,
|
||||
'paneProperties.legendProperties.showBarChange': false,
|
||||
'paneProperties.backgroundType': 'solid',
|
||||
|
||||
'mainSeriesProperties.style': 1,
|
||||
'mainSeriesProperties.candleStyle.upColor': Color(colors.positive).hex(),
|
||||
'mainSeriesProperties.candleStyle.borderUpColor': Color(colors.positive).hex(),
|
||||
'mainSeriesProperties.candleStyle.wickUpColor': Color(colors.positive).hex(),
|
||||
'mainSeriesProperties.candleStyle.downColor': Color(colors.negative).hex(),
|
||||
'mainSeriesProperties.candleStyle.borderDownColor': Color(colors.negative).hex(),
|
||||
'mainSeriesProperties.candleStyle.wickDownColor': Color(colors.negative).hex(),
|
||||
'mainSeriesProperties.candleStyle.upColor': theme.positive,
|
||||
'mainSeriesProperties.candleStyle.borderUpColor': theme.positive,
|
||||
'mainSeriesProperties.candleStyle.wickUpColor': theme.positive,
|
||||
'mainSeriesProperties.candleStyle.downColor': theme.negative,
|
||||
'mainSeriesProperties.candleStyle.borderDownColor': theme.negative,
|
||||
'mainSeriesProperties.candleStyle.wickDownColor': theme.negative,
|
||||
'mainSeriesProperties.statusViewStyle.symbolTextSource': 'ticker',
|
||||
|
||||
'scalesProperties.textColor': Color(colors.text1).hex(),
|
||||
'scalesProperties.backgroundColor': Color(colors.layer2).hex(),
|
||||
'scalesProperties.lineColor': Color(colors.layer3).hex(),
|
||||
'scalesProperties.textColor': theme.textPrimary,
|
||||
'scalesProperties.backgroundColor': theme.layer2,
|
||||
'scalesProperties.lineColor': theme.layer3,
|
||||
},
|
||||
studies_overrides: {
|
||||
'volume.volume.color.0': Color(colors.negative).hex(),
|
||||
'volume.volume.color.1': Color(colors.positive).hex(),
|
||||
'volume.volume.color.0': theme.negative,
|
||||
'volume.volume.color.1': theme.positive,
|
||||
'volume.volume ma.visible': false,
|
||||
'relative strength index.plot.color': Color(colors.accent).hex(),
|
||||
'relative strength index.plot.color': theme.accent,
|
||||
'relative strength index.plot.linewidth': 1.5,
|
||||
'relative strength index.hlines background.color': '#134A9F',
|
||||
},
|
||||
loading_screen: {
|
||||
backgroundColor: Color(colors.layer2).hex(),
|
||||
foregroundColor: Color(colors.layer2).hex(),
|
||||
backgroundColor: theme.layer2,
|
||||
foregroundColor: theme.layer2,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { createConfig, configureChains, mainnet, Chain } from 'wagmi';
|
||||
import { goerli } from 'wagmi/chains';
|
||||
import type { PrivyClientConfig } from '@privy-io/react-auth';
|
||||
|
||||
import {
|
||||
arbitrum,
|
||||
@@ -86,19 +85,6 @@ export const WAGMI_SUPPORTED_CHAINS: Chain[] = [
|
||||
kava,
|
||||
];
|
||||
|
||||
export const privyConfig: PrivyClientConfig = {
|
||||
embeddedWallets: {
|
||||
createOnLogin: 'users-without-wallets',
|
||||
requireUserPasswordOnCreate: true,
|
||||
noPromptOnSignature: true,
|
||||
},
|
||||
loginMethods: ['email', 'sms', 'twitter', 'google', 'apple'],
|
||||
appearance: {
|
||||
theme: '#28283c',
|
||||
},
|
||||
defaultChain: sepolia
|
||||
};
|
||||
|
||||
const { chains, publicClient, webSocketPublicClient } = configureChains(
|
||||
WAGMI_SUPPORTED_CHAINS,
|
||||
[
|
||||
|
||||
@@ -62,12 +62,6 @@ export const getWalletConnection = ({
|
||||
type: WalletConnectionType.CosmosSigner,
|
||||
};
|
||||
}
|
||||
|
||||
case WalletConnectionType.Privy: {
|
||||
return {
|
||||
type: WalletConnectionType.Privy,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -259,8 +259,8 @@ Styled.ProfileIcon = styled.div`
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--theme-classic-color-yellow) 0%,
|
||||
var(--theme-classic-color-red) 100%
|
||||
${({ theme }) => theme.profileYellow} 0%,
|
||||
${({ theme }) => theme.profileRed} 100%
|
||||
);
|
||||
`;
|
||||
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
:root {
|
||||
/* Parameters */
|
||||
|
||||
/*
|
||||
--layer-base-hue
|
||||
--layer-base-saturation
|
||||
--layer-base-lightness
|
||||
|
||||
--color-text-0
|
||||
--color-text-1
|
||||
--color-text-2
|
||||
|
||||
--color-accent
|
||||
--color-positive
|
||||
--color-negative
|
||||
--color-success
|
||||
--color-warning
|
||||
--color-error
|
||||
--color-favorite
|
||||
*/
|
||||
|
||||
/* Computed: Layers */
|
||||
|
||||
--color-layer-0: hsl(
|
||||
var(--layer-base-hue),
|
||||
var(--layer-base-saturation),
|
||||
calc(var(--layer-base-lightness) - 12%)
|
||||
);
|
||||
|
||||
--color-layer-1: hsl(
|
||||
var(--layer-base-hue),
|
||||
var(--layer-base-saturation),
|
||||
calc(var(--layer-base-lightness) - 8%)
|
||||
);
|
||||
|
||||
--color-layer-2: hsl(
|
||||
var(--layer-base-hue),
|
||||
var(--layer-base-saturation),
|
||||
calc(var(--layer-base-lightness) - 4%)
|
||||
);
|
||||
|
||||
--color-layer-3: hsl(
|
||||
var(--layer-base-hue),
|
||||
var(--layer-base-saturation),
|
||||
var(--layer-base-lightness)
|
||||
);
|
||||
|
||||
--color-layer-4: hsl(
|
||||
var(--layer-base-hue),
|
||||
var(--layer-base-saturation),
|
||||
calc(var(--layer-base-lightness) + 4%)
|
||||
);
|
||||
|
||||
--color-layer-5: hsl(
|
||||
var(--layer-base-hue),
|
||||
calc(var(--layer-base-saturation) - 2%),
|
||||
calc(var(--layer-base-lightness) + 7%)
|
||||
);
|
||||
|
||||
--color-layer-6: hsl(
|
||||
var(--layer-base-hue),
|
||||
calc(var(--layer-base-saturation) - 4%),
|
||||
calc(var(--layer-base-lightness) + 10%)
|
||||
);
|
||||
|
||||
--color-layer-7: hsla(var(--layer-base-hue), 0%, 100%, 0.07);
|
||||
|
||||
--color-gradient-base-0: hsl(
|
||||
var(--layer-base-hue),
|
||||
calc(var(--layer-base-saturation) - 5%),
|
||||
var(--layer-base-lightness)
|
||||
);
|
||||
|
||||
--color-gradient-base-1: hsl(
|
||||
var(--layer-base-hue),
|
||||
calc(var(--layer-base-saturation) - 1%),
|
||||
calc(var(--layer-base-lightness) + 7%)
|
||||
);
|
||||
|
||||
/* Computed: Borders */
|
||||
|
||||
--color-border: var(--color-layer-5);
|
||||
--color-border-white: hsla(0, 0%, 100%, 0.2);
|
||||
--color-border-red: hsla(360, 73%, 61%, 0.2);
|
||||
}
|
||||
|
||||
/* Theme: Classic (default) */
|
||||
:root {
|
||||
/* Constants */
|
||||
|
||||
--theme-classic-hue-purple: 240;
|
||||
--theme-classic-color-green: hsl(159, 67%, 39%);
|
||||
--theme-classic-color-yellow: hsl(36, 100%, 64%);
|
||||
--theme-classic-color-red: hsl(360, 73%, 61%);
|
||||
|
||||
/* Parameters */
|
||||
|
||||
--layer-base-hue: var(--theme-classic-hue-purple);
|
||||
--layer-base-saturation: 20%;
|
||||
--layer-base-lightness: 16%;
|
||||
|
||||
--color-text-0: hsl(245, 11%, 55%);
|
||||
--color-text-1: hsl(244, 18%, 81%);
|
||||
--color-text-2: hsl(240, 43%, 99%);
|
||||
|
||||
--color-accent: hsl(var(--theme-classic-hue-purple), 100%, 70%);
|
||||
--color-positive: var(--theme-classic-color-green);
|
||||
--color-negative: var(--theme-classic-color-red);
|
||||
--color-success: var(--theme-classic-color-green);
|
||||
--color-warning: var(--theme-classic-color-yellow);
|
||||
--color-error: var(--theme-classic-color-red);
|
||||
--color-favorite: var(--theme-classic-color-yellow);
|
||||
|
||||
--color-white: #fff;
|
||||
--color-black: #000;
|
||||
|
||||
--color-gradient-positive: hsla(158, 49%, 48%, 0.16);
|
||||
--color-gradient-negative: hsla(0, 100%, 66%, 0.16);
|
||||
--color-accent-faded: hsla(var(--theme-classic-hue-purple), 100%, 70%, 0.16);
|
||||
|
||||
--color-risk-low: var(--theme-classic-color-green);
|
||||
--color-risk-medium: var(--theme-classic-color-yellow);
|
||||
--color-risk-high: var(--theme-classic-color-red);
|
||||
}
|
||||
|
||||
/* Theme: Light */
|
||||
:root.theme-light {
|
||||
/* Constants */
|
||||
|
||||
--theme-light-hue-purple: 234;
|
||||
--theme-light-color-green: hsl(159, 67%, 39%);
|
||||
--theme-light-color-yellow: hsl(36, 100%, 64%);
|
||||
--theme-light-color-red: hsl(360, 73%, 61%);
|
||||
|
||||
/* Parameters */
|
||||
|
||||
--layer-base-hue: var(--theme-light-hue-purple);
|
||||
--layer-base-saturation: 0%;
|
||||
--layer-base-lightness: 86%;
|
||||
|
||||
--color-text-0: hsl(0, 0%, 55%);
|
||||
--color-text-1: hsl(0, 0%, 40%);
|
||||
--color-text-2: hsl(0, 0%, 5%);
|
||||
|
||||
--color-accent: hsl(var(--theme-light-hue-purple), 100%, 70%);
|
||||
--color-positive: var(--theme-light-color-green);
|
||||
--color-negative: var(--theme-light-color-red);
|
||||
--color-success: var(--theme-light-color-green);
|
||||
--color-warning: var(--theme-light-color-yellow);
|
||||
--color-error: var(--theme-light-color-red);
|
||||
--color-favorite: var(--theme-light-color-yellow);
|
||||
}
|
||||
|
||||
/* Theme: Dark */
|
||||
:root.theme-dark {
|
||||
/* Constants */
|
||||
|
||||
--theme-dark-hue-purple: 240;
|
||||
--theme-dark-color-green: hsl(159, 67%, 39%);
|
||||
--theme-dark-color-yellow: hsl(36, 100%, 64%);
|
||||
--theme-dark-color-red: hsl(360, 73%, 61%);
|
||||
|
||||
/* Parameters */
|
||||
|
||||
--layer-base-hue: 0;
|
||||
--layer-base-saturation: 0%;
|
||||
--layer-base-lightness: 16%;
|
||||
|
||||
--color-text-0: hsl(0, 0%, 47%);
|
||||
--color-text-1: hsl(0, 0%, 67%);
|
||||
--color-text-2: hsl(0, 0%, 100%);
|
||||
|
||||
--color-accent: hsl(var(--theme-dark-hue-purple), 100%, 70%);
|
||||
--color-positive: var(--theme-dark-color-green);
|
||||
--color-negative: var(--theme-dark-color-red);
|
||||
--color-success: var(--theme-dark-color-green);
|
||||
--color-warning: var(--theme-dark-color-yellow);
|
||||
--color-error: var(--theme-dark-color-red);
|
||||
--color-favorite: var(--theme-dark-color-yellow);
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
import { css } from 'styled-components';
|
||||
|
||||
import { type RiskLevels } from '@/constants/abacus';
|
||||
|
||||
import { AppTheme } from '@/state/configs';
|
||||
|
||||
const BaseElements = {
|
||||
[AppTheme.Classic]: {
|
||||
hue: 240,
|
||||
saturation: 20,
|
||||
lightness: 16,
|
||||
},
|
||||
[AppTheme.Dark]: {
|
||||
hue: 0,
|
||||
saturation: 0,
|
||||
lightness: 16,
|
||||
},
|
||||
[AppTheme.Light]: {
|
||||
hue: 234,
|
||||
saturation: 0,
|
||||
lightness: 86,
|
||||
},
|
||||
};
|
||||
|
||||
const LayerColors = ({ theme }: { theme: AppTheme }) => {
|
||||
const { hue, saturation, lightness } = BaseElements[theme];
|
||||
|
||||
return {
|
||||
layer0: `hsl(${hue}, ${saturation}%, ${lightness - 12}%)`,
|
||||
layer1: `hsl(${hue}, ${saturation}%, ${lightness - 8}%)`,
|
||||
layer2: `hsl(${hue}, ${saturation}%, ${lightness - 4}%)`,
|
||||
layer3: `hsl(${hue}, ${saturation}%, ${lightness}%)`,
|
||||
layer4: `hsl(${hue}, ${saturation}%, ${lightness + 4}%)`,
|
||||
layer5: `hsl(${hue}, ${saturation - 2}%, ${lightness + 7}%)`,
|
||||
layer6: `hsl(${hue}, ${saturation - 4}%, ${lightness + 10}%)`,
|
||||
};
|
||||
};
|
||||
|
||||
const AccentColor = ({ theme }: { theme: AppTheme }) => {
|
||||
const purpleHue = {
|
||||
Classic: 240,
|
||||
Dark: 240,
|
||||
Light: 234,
|
||||
}[theme];
|
||||
|
||||
return {
|
||||
accent: `hsl(${purpleHue}, 100%, 70%)`,
|
||||
};
|
||||
};
|
||||
|
||||
export const Colors = {
|
||||
[AppTheme.Classic]: {
|
||||
...LayerColors({ theme: AppTheme.Classic }),
|
||||
text0: 'hsl(245, 11%, 55%)',
|
||||
text1: 'hsl(244, 18%, 81%)',
|
||||
text2: 'hsl(240, 43%, 99%)',
|
||||
|
||||
...AccentColor({ theme: AppTheme.Classic }),
|
||||
green: 'hsl(159, 67%, 39%)',
|
||||
yellow: 'hsl(36, 100%, 64%)',
|
||||
red: 'hsl(360, 73%, 61%)',
|
||||
|
||||
positive: 'hsl(159, 67%, 39%)',
|
||||
negative: 'hsl(360, 73%, 61%)',
|
||||
|
||||
success: 'hsl(159, 67%, 39%)',
|
||||
warning: 'hsl(36, 100%, 64%)',
|
||||
error: 'hsl(360, 73%, 61%)',
|
||||
|
||||
favorite: 'hsl(36, 100%, 64%)',
|
||||
},
|
||||
[AppTheme.Dark]: {
|
||||
...LayerColors({ theme: AppTheme.Dark }),
|
||||
text0: 'hsl(0, 0%, 47%)',
|
||||
text1: 'hsl(0, 0%, 67%)',
|
||||
text2: 'hsl(0, 0%, 100%)',
|
||||
|
||||
...AccentColor({ theme: AppTheme.Dark }),
|
||||
green: 'hsl(159, 67%, 39%)',
|
||||
yellow: 'hsl(36, 100%, 64%)',
|
||||
red: 'hsl(360, 73%, 61%)',
|
||||
|
||||
positive: 'hsl(159, 67%, 39%)',
|
||||
negative: 'hsl(360, 73%, 61%)',
|
||||
|
||||
success: 'hsl(159, 67%, 39%)',
|
||||
warning: 'hsl(36, 100%, 64%)',
|
||||
error: 'hsl(360, 73%, 61%)',
|
||||
|
||||
favorite: 'hsl(36, 100%, 64%)',
|
||||
},
|
||||
[AppTheme.Light]: {
|
||||
...LayerColors({ theme: AppTheme.Light }),
|
||||
text0: 'hsl(0, 0%, 55%)',
|
||||
text1: 'hsl(0, 0%, 40%)',
|
||||
text2: 'hsl(0, 0%, 5%)',
|
||||
|
||||
...AccentColor({ theme: AppTheme.Light }),
|
||||
green: 'hsl(159, 67%, 39%)',
|
||||
yellow: 'hsl(36, 100%, 64%)',
|
||||
red: 'hsl(360, 73%, 61%)',
|
||||
|
||||
positive: 'hsl(159, 67%, 39%)',
|
||||
negative: 'hsl(360, 73%, 61%)',
|
||||
|
||||
success: 'hsl(159, 67%, 39%)',
|
||||
warning: 'hsl(36, 100%, 64%)',
|
||||
error: 'hsl(360, 73%, 61%)',
|
||||
|
||||
favorite: 'hsl(36, 100%, 64%)',
|
||||
},
|
||||
};
|
||||
|
||||
export const UsageColorFromRiskLevel = (riskLevel: RiskLevels) =>
|
||||
({
|
||||
low: css`
|
||||
color: var(--color-risk-low);
|
||||
`,
|
||||
medium: css`
|
||||
color: var(--color-risk-medium);
|
||||
`,
|
||||
high: css`
|
||||
color: var(--color-risk-high);
|
||||
`,
|
||||
}[riskLevel.name]);
|
||||
@@ -21,7 +21,7 @@ export const formMixins: Record<
|
||||
--input-radius: 0.5em;
|
||||
--input-height: var(--form-input-height);
|
||||
--input-width: 100%;
|
||||
--input-backgroundColor: var(--color-layer-4);
|
||||
--input-backgroundColor: ${({ theme }) => theme.inputBackground};
|
||||
--input-borderColor: var(--color-layer-6);
|
||||
|
||||
${layoutMixins.row}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { createGlobalStyle } from 'styled-components';
|
||||
|
||||
export const GlobalStyle = createGlobalStyle`
|
||||
:root {
|
||||
--color-layer-0: ${({ theme }) => theme.layer0};
|
||||
--color-layer-1: ${({ theme }) => theme.layer1};
|
||||
--color-layer-2: ${({ theme }) => theme.layer2};
|
||||
--color-layer-3: ${({ theme }) => theme.layer3};
|
||||
--color-layer-4: ${({ theme }) => theme.layer4};
|
||||
--color-layer-5: ${({ theme }) => theme.layer5};
|
||||
--color-layer-6: ${({ theme }) => theme.layer6};
|
||||
--color-layer-7: ${({ theme }) => theme.layer7};
|
||||
|
||||
--color-border: ${({ theme }) => theme.borderDefault};
|
||||
--color-border-white: ${({ theme }) => theme.borderButton};
|
||||
--color-border-red: ${({ theme }) => theme.borderDestructive};
|
||||
|
||||
--color-text-0: ${({ theme }) => theme.textTertiary};
|
||||
--color-text-1: ${({ theme }) => theme.textSecondary};
|
||||
--color-text-2: ${({ theme }) => theme.textPrimary};
|
||||
|
||||
--color-gradient-base-0: ${({ theme }) => theme.gradientBase0};
|
||||
--color-gradient-base-1: ${({ theme }) => theme.gradientBase1};
|
||||
|
||||
--color-accent: ${({ theme }) => theme.accent};
|
||||
--color-accent-faded: ${({ theme }) => theme.accentFaded};
|
||||
--color-favorite: ${({ theme }) => theme.favorite};
|
||||
|
||||
--color-success: ${({ theme }) => theme.success};
|
||||
--color-warning: ${({ theme }) => theme.warning};
|
||||
--color-error: ${({ theme }) => theme.error};
|
||||
|
||||
--color-positive: ${({ theme }) => theme.positive};
|
||||
--color-negative: ${({ theme }) => theme.negative};
|
||||
--color-gradient-positive: ${({ theme }) => theme.positiveFaded};
|
||||
--color-gradient-negative: ${({ theme }) => theme.negativeFaded};
|
||||
|
||||
--color-risk-low: ${({ theme }) => theme.riskLow};
|
||||
--color-risk-medium: ${({ theme }) => theme.riskMedium};
|
||||
--color-risk-high: ${({ theme }) => theme.riskHigh};
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,157 @@
|
||||
import { AppTheme } from '@/state/configs';
|
||||
import { ThemeColors } from '@/constants/styles/colors';
|
||||
import { ColorToken, OpacityToken } from '@/constants/styles/base';
|
||||
import { generateFadedColorVariant } from '@/lib/styles';
|
||||
|
||||
const ClassicTheme: ThemeColors = {
|
||||
layer0: ColorToken.GrayBlue7,
|
||||
layer1: ColorToken.GrayBlue6,
|
||||
layer2: ColorToken.GrayBlue5,
|
||||
layer3: ColorToken.GrayBlue4,
|
||||
layer4: ColorToken.GrayBlue3,
|
||||
layer5: ColorToken.GrayBlue2,
|
||||
layer6: ColorToken.GrayBlue1,
|
||||
layer7: ColorToken.GrayBlue0,
|
||||
|
||||
borderDefault: ColorToken.GrayBlue2,
|
||||
borderDestructive: generateFadedColorVariant(ColorToken.Red2, OpacityToken.Opacity20),
|
||||
borderButton: generateFadedColorVariant(ColorToken.White, OpacityToken.Opacity20),
|
||||
|
||||
textPrimary: ColorToken.LightGray2,
|
||||
textSecondary: ColorToken.GrayPurple1,
|
||||
textTertiary: ColorToken.GrayPurple2,
|
||||
|
||||
gradientBase0: ColorToken.DarkGray9,
|
||||
gradientBase1: ColorToken.GrayBlue2,
|
||||
|
||||
accent: ColorToken.Purple1,
|
||||
accentFaded: generateFadedColorVariant(ColorToken.Purple1, OpacityToken.Opacity16),
|
||||
favorite: ColorToken.Yellow0,
|
||||
|
||||
success: ColorToken.Green1,
|
||||
warning: ColorToken.Yellow0,
|
||||
error: ColorToken.Red2,
|
||||
|
||||
positive: ColorToken.Green1,
|
||||
negative: ColorToken.Red2,
|
||||
positiveFaded: generateFadedColorVariant(ColorToken.Green1, OpacityToken.Opacity16),
|
||||
negativeFaded: generateFadedColorVariant(ColorToken.Red2, OpacityToken.Opacity16),
|
||||
|
||||
riskLow: ColorToken.Green1,
|
||||
riskMedium: ColorToken.Yellow0,
|
||||
riskHigh: ColorToken.Red2,
|
||||
|
||||
logoFill: ColorToken.White,
|
||||
profileYellow: ColorToken.Yellow1,
|
||||
profileRed: ColorToken.Red2,
|
||||
|
||||
inputBackground: ColorToken.GrayBlue3,
|
||||
popoverBackground: generateFadedColorVariant(ColorToken.GrayBlue4, OpacityToken.Opacity90),
|
||||
switchThumbActiveBackground: ColorToken.White,
|
||||
toggleBackground: ColorToken.GrayBlue3,
|
||||
tooltipBackground: generateFadedColorVariant(ColorToken.GrayBlue3, OpacityToken.Opacity66),
|
||||
};
|
||||
|
||||
const DarkTheme: ThemeColors = {
|
||||
layer0: ColorToken.Black,
|
||||
layer1: ColorToken.DarkGray11,
|
||||
layer2: ColorToken.DarkGray13,
|
||||
layer3: ColorToken.DarkGray10,
|
||||
layer4: ColorToken.DarkGray6,
|
||||
layer5: ColorToken.DarkGray5,
|
||||
layer6: ColorToken.DarkGray4,
|
||||
layer7: ColorToken.DarkGray2,
|
||||
|
||||
borderDefault: ColorToken.DarkGray4,
|
||||
borderDestructive: generateFadedColorVariant(ColorToken.Red0, OpacityToken.Opacity20),
|
||||
borderButton: generateFadedColorVariant(ColorToken.White, OpacityToken.Opacity20),
|
||||
|
||||
textPrimary: ColorToken.LightGray0,
|
||||
textSecondary: ColorToken.MediumGray0,
|
||||
textTertiary: ColorToken.DarkGray0,
|
||||
|
||||
gradientBase0: ColorToken.DarkGray8,
|
||||
gradientBase1: ColorToken.DarkGray5,
|
||||
|
||||
accent: ColorToken.Purple0,
|
||||
accentFaded: generateFadedColorVariant(ColorToken.Purple0, OpacityToken.Opacity16),
|
||||
favorite: ColorToken.Yellow0,
|
||||
|
||||
success: ColorToken.Green0,
|
||||
warning: ColorToken.Yellow0,
|
||||
error: ColorToken.Red0,
|
||||
|
||||
positive: ColorToken.Green0,
|
||||
negative: ColorToken.Red0,
|
||||
positiveFaded: generateFadedColorVariant(ColorToken.Green0, OpacityToken.Opacity16),
|
||||
negativeFaded: generateFadedColorVariant(ColorToken.Red0, OpacityToken.Opacity16),
|
||||
|
||||
riskLow: ColorToken.Green0,
|
||||
riskMedium: ColorToken.Yellow0,
|
||||
riskHigh: ColorToken.Red0,
|
||||
|
||||
logoFill: ColorToken.White,
|
||||
profileYellow: ColorToken.Yellow1,
|
||||
profileRed: ColorToken.Red2,
|
||||
|
||||
inputBackground: ColorToken.DarkGray6,
|
||||
popoverBackground: generateFadedColorVariant(ColorToken.DarkGray8, OpacityToken.Opacity90),
|
||||
switchThumbActiveBackground: ColorToken.White,
|
||||
toggleBackground: ColorToken.DarkGray6,
|
||||
tooltipBackground: generateFadedColorVariant(ColorToken.DarkGray6, OpacityToken.Opacity66),
|
||||
};
|
||||
|
||||
const LightTheme: ThemeColors = {
|
||||
layer0: ColorToken.White,
|
||||
layer1: ColorToken.LightGray6,
|
||||
layer2: ColorToken.White,
|
||||
layer3: ColorToken.LightGray1,
|
||||
layer4: ColorToken.White,
|
||||
layer5: ColorToken.LightGray4,
|
||||
layer6: ColorToken.LightGray9,
|
||||
layer7: ColorToken.MediumGray1,
|
||||
|
||||
borderDefault: ColorToken.LightGray10,
|
||||
borderDestructive: generateFadedColorVariant(ColorToken.Red1, OpacityToken.Opacity20),
|
||||
borderButton: generateFadedColorVariant(ColorToken.Black, OpacityToken.Opacity20),
|
||||
|
||||
textPrimary: ColorToken.DarkGray12,
|
||||
textSecondary: ColorToken.DarkGray3,
|
||||
textTertiary: ColorToken.DarkGray1,
|
||||
|
||||
gradientBase0: ColorToken.LightGray8,
|
||||
gradientBase1: ColorToken.LightGray5,
|
||||
|
||||
accent: ColorToken.Purple0,
|
||||
accentFaded: generateFadedColorVariant(ColorToken.Purple0, OpacityToken.Opacity16),
|
||||
favorite: ColorToken.Yellow0,
|
||||
|
||||
success: ColorToken.Green2,
|
||||
warning: ColorToken.Yellow0,
|
||||
error: ColorToken.Red1,
|
||||
|
||||
positive: ColorToken.Green2,
|
||||
negative: ColorToken.Red1,
|
||||
positiveFaded: generateFadedColorVariant(ColorToken.Green2, OpacityToken.Opacity16),
|
||||
negativeFaded: generateFadedColorVariant(ColorToken.Red1, OpacityToken.Opacity16),
|
||||
|
||||
riskLow: ColorToken.Green2,
|
||||
riskMedium: ColorToken.Yellow0,
|
||||
riskHigh: ColorToken.Red1,
|
||||
|
||||
logoFill: ColorToken.Black,
|
||||
profileYellow: ColorToken.Yellow1,
|
||||
profileRed: ColorToken.Red2,
|
||||
|
||||
inputBackground: ColorToken.White,
|
||||
popoverBackground: generateFadedColorVariant(ColorToken.LightGray8, OpacityToken.Opacity90),
|
||||
switchThumbActiveBackground: ColorToken.White,
|
||||
toggleBackground: ColorToken.LightGray4,
|
||||
tooltipBackground: generateFadedColorVariant(ColorToken.LightGray7, OpacityToken.Opacity66),
|
||||
};
|
||||
|
||||
export const Themes = {
|
||||
[AppTheme.Classic]: ClassicTheme,
|
||||
[AppTheme.Dark]: DarkTheme,
|
||||
[AppTheme.Light]: LightTheme,
|
||||
};
|
||||
@@ -1,4 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import styled, { AnyStyledComponent } from 'styled-components';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { AlertType } from '@/constants/alerts';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
@@ -11,7 +13,7 @@ import { Button } from '@/components/Button';
|
||||
import { Icon } from '@/components/Icon';
|
||||
import { Link } from '@/components/Link';
|
||||
|
||||
import { useAccounts, useBreakpoints, useStringGetter, useURLConfigs } from '@/hooks';
|
||||
import { useAccounts, useStringGetter, useURLConfigs } from '@/hooks';
|
||||
import { useDisplayedWallets } from '@/hooks/useDisplayedWallets';
|
||||
|
||||
import { breakpoints } from '@/styles';
|
||||
@@ -25,8 +27,6 @@ export const ChooseWallet = () => {
|
||||
|
||||
const { selectWalletType, selectedWalletType, selectedWalletError } = useAccounts();
|
||||
|
||||
const { isMobile } = useBreakpoints();
|
||||
|
||||
return (
|
||||
<>
|
||||
{selectedWalletType && selectedWalletError && (
|
||||
@@ -56,11 +56,7 @@ export const ChooseWallet = () => {
|
||||
slotLeft={<Styled.Icon iconComponent={wallets[walletType].icon} />}
|
||||
size={ButtonSize.Small}
|
||||
>
|
||||
<div>
|
||||
{walletType !== WalletType.Privy && import.meta.env.VITE_PRIVY_APP_ID
|
||||
? stringGetter({ key: wallets[walletType].stringKey })
|
||||
: `Socials ${isMobile ? '' : '(Email, SMS, etc.)'}`}
|
||||
</div>
|
||||
<div>{stringGetter({ key: wallets[walletType].stringKey })}</div>
|
||||
</Styled.WalletButton>
|
||||
))}
|
||||
</Styled.Wallets>
|
||||
|
||||
@@ -34,30 +34,11 @@ export const ChainSelectMenu = ({ label, selectedChain, onSelectChain }: Element
|
||||
slotBefore: <Styled.Img src={chain.iconUrl} alt="" />,
|
||||
}));
|
||||
|
||||
const selectedOption = selectedChain === 'coinbase' ? {
|
||||
stringKey: 'Coinbase',
|
||||
iconUrl: '/wallets/coinbase-wallet.png',
|
||||
} : chains.find((item) => item.type === selectedChain);
|
||||
|
||||
const exchanges = [
|
||||
{
|
||||
value: 'coinbase',
|
||||
label: 'Coinbase',
|
||||
onSelect: () => {
|
||||
onSelectChain('coinbase');
|
||||
},
|
||||
slotBefore: <Styled.Img src="/wallets/coinbase-wallet.png" alt="" />,
|
||||
}
|
||||
];
|
||||
const selectedOption = chains.find((item) => item.type === selectedChain);
|
||||
|
||||
return (
|
||||
<SearchSelectMenu
|
||||
items={[
|
||||
{
|
||||
group: 'exchanges',
|
||||
groupLabel: 'Exchanges',
|
||||
items: exchanges,
|
||||
},
|
||||
{
|
||||
group: 'chains',
|
||||
groupLabel: stringGetter({ key: STRING_KEYS.CHAINS }),
|
||||
|
||||
@@ -38,14 +38,12 @@ import abacusStateManager from '@/lib/abacus';
|
||||
import { MustBigNumber } from '@/lib/numbers';
|
||||
import { getNobleChainId, NATIVE_TOKEN_ADDRESS } from '@/lib/squid';
|
||||
import { log } from '@/lib/telemetry';
|
||||
import { parseWalletError, truncateAddress } from '@/lib/wallet';
|
||||
import { parseWalletError } from '@/lib/wallet';
|
||||
|
||||
import { ChainSelectMenu } from './ChainSelectMenu';
|
||||
import { TokenSelectMenu } from './TokenSelectMenu';
|
||||
|
||||
import { DepositButtonAndReceipt } from './DepositForm/DepositButtonAndReceipt';
|
||||
import { QrCode } from '@/components/QrCode';
|
||||
import { CopyButton } from '@/components/CopyButton';
|
||||
|
||||
type DepositFormProps = {
|
||||
onDeposit?: () => void;
|
||||
@@ -57,9 +55,8 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { selectedNetwork } = useSelectedNetwork();
|
||||
const [isCoinbase, setIsCoinbase] = useState(false);
|
||||
|
||||
const { evmAddress, signerWagmi, publicClientWagmi, nobleAddress } = useAccounts();
|
||||
const { evmAddress, signerWagmi, publicClientWagmi } = useAccounts();
|
||||
|
||||
const { addTransferNotification } = useLocalNotifications();
|
||||
|
||||
@@ -136,10 +133,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
||||
}, [error]);
|
||||
|
||||
const onSelectChain = useCallback((chain: string) => {
|
||||
if (chain === 'coinbase') {
|
||||
setIsCoinbase(true);
|
||||
} else if (chain) {
|
||||
setIsCoinbase(false);
|
||||
if (chain) {
|
||||
abacusStateManager.clearTransferInputValues();
|
||||
abacusStateManager.setTransferValue({
|
||||
field: TransferInputField.chain,
|
||||
@@ -241,6 +235,10 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
||||
throw new Error('Missing request payload');
|
||||
}
|
||||
|
||||
if (isCctp && !abacusStateManager.chainTransactions.isNobleClientConnected) {
|
||||
throw new Error('Noble RPC endpoint unaccessible');
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
await validateTokenApproval();
|
||||
@@ -370,43 +368,9 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
||||
return <LoadingSpace id="DepositForm" />;
|
||||
}
|
||||
|
||||
if (isCoinbase) {
|
||||
return (
|
||||
<Styled.Form onSubmit={onSubmit}>
|
||||
<ChainSelectMenu
|
||||
selectedChain={isCoinbase ? 'coinbase' : chainIdStr || undefined}
|
||||
onSelectChain={onSelectChain}
|
||||
/>
|
||||
{nobleAddress && (
|
||||
<>
|
||||
<Styled.ReceiveQr
|
||||
side="bottom"
|
||||
detailItems={[
|
||||
{
|
||||
key: 'nobleAddress',
|
||||
label: "Noble Address",
|
||||
value: nobleAddress,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<QrCode size={432} value={nobleAddress} />
|
||||
</Styled.ReceiveQr>
|
||||
<p>
|
||||
* This address only supports transfers of USDC to the Noble chain.
|
||||
</p>
|
||||
<CopyButton value={nobleAddress} />
|
||||
</>
|
||||
)}
|
||||
</Styled.Form>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Styled.Form onSubmit={onSubmit}>
|
||||
<ChainSelectMenu
|
||||
selectedChain={isCoinbase ? 'coinbase' : chainIdStr || undefined}
|
||||
onSelectChain={onSelectChain}
|
||||
/>
|
||||
<ChainSelectMenu selectedChain={chainIdStr || undefined} onSelectChain={onSelectChain} />
|
||||
<TokenSelectMenu selectedToken={sourceToken || undefined} onSelectToken={onSelectToken} />
|
||||
<Styled.WithDetailsReceipt side="bottom" detailItems={amountInputReceipt}>
|
||||
<FormInput
|
||||
@@ -467,13 +431,3 @@ Styled.TransactionInfo = styled.span`
|
||||
Styled.FormInputButton = styled(Button)`
|
||||
${formMixins.inputInnerButton}
|
||||
`;
|
||||
|
||||
Styled.Exchange = styled.div`
|
||||
${layoutMixins.flexColumn}
|
||||
gap: 1rem;
|
||||
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
Styled.ReceiveQr = styled(WithDetailsReceipt)`
|
||||
`;
|
||||
|
||||
@@ -148,6 +148,10 @@ export const WithdrawForm = () => {
|
||||
throw new Error('Invalid request payload');
|
||||
}
|
||||
|
||||
if (isCctp && !abacusStateManager.chainTransactions.isNobleClientConnected) {
|
||||
throw new Error('Noble RPC endpoint unaccessible');
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
setError(undefined);
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ export const TradeSideToggle = memo(() => {
|
||||
const ToggleContainer = styled(ToggleGroup)<{ value: OrderSide }>`
|
||||
--toggle-radius: 0.5em;
|
||||
--toggle-color: var(--color-negative);
|
||||
--toggle-background: ${({ theme }) => theme.toggleBackground};
|
||||
|
||||
${({ value }) =>
|
||||
value === OrderSide.BUY &&
|
||||
@@ -52,7 +53,7 @@ const ToggleContainer = styled(ToggleGroup)<{ value: OrderSide }>`
|
||||
`}
|
||||
|
||||
border-radius: var(--toggle-radius);
|
||||
background-color: var(--color-layer-4);
|
||||
background-color: var(--toggle-background);
|
||||
position: relative;
|
||||
|
||||
> button {
|
||||
|
||||
@@ -2,7 +2,6 @@ import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import path from 'path';
|
||||
import svgr from 'vite-plugin-svgr';
|
||||
import { VitePWA } from 'vite-plugin-pwa';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ mode }) => ({
|
||||
@@ -51,12 +50,6 @@ export default defineConfig(({ mode }) => ({
|
||||
svgr({
|
||||
exportAsDefault: true,
|
||||
}),
|
||||
VitePWA({
|
||||
registerType: 'autoUpdate',
|
||||
devOptions: {
|
||||
enabled: true,
|
||||
},
|
||||
}),
|
||||
],
|
||||
publicDir: 'public',
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user