Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be57b2facf |
@@ -8,14 +8,7 @@ VITE_V3_TOKEN_ADDRESS=
|
||||
VITE_TOKEN_MIGRATION_URI=
|
||||
|
||||
AMPLITUDE_API_KEY=
|
||||
AMPLITUDE_SERVER_URL=
|
||||
BUGSNAG_API_KEY=
|
||||
IOS_APP_ID=
|
||||
INTERCOM_APP_ID=
|
||||
STATUS_PAGE_SCRIPT_URI=
|
||||
|
||||
SMARTBANNER_APP_NAME=
|
||||
SMARTBANNER_ORG_NAME=
|
||||
SMARTBANNER_ICON_URL=
|
||||
SMARTBANNER_APPSTORE_URL=
|
||||
SMARTBANNER_GOOGLEPLAY_URL=
|
||||
|
||||
@@ -39,7 +39,6 @@ jobs:
|
||||
pnpm run build:inject-amplitude
|
||||
pnpm run build:inject-bugsnag
|
||||
pnpm run build:inject-statuspage
|
||||
pnpm run build:inject-smartbanner
|
||||
sh scripts/inject-app-deeplinks.sh
|
||||
|
||||
- name: Upload to IPFS via web3.storage
|
||||
|
||||
@@ -2,102 +2,61 @@ import '@/polyfills';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import styled from 'styled-components';
|
||||
import { WagmiConfig } from 'wagmi';
|
||||
import { GrazProvider } from 'graz';
|
||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||
|
||||
import { SupportedLocales } from '@/constants/localization';
|
||||
|
||||
import { AccountsProvider } from '@/hooks/useAccounts';
|
||||
import { AppThemeAndColorModeProvider } from '@/hooks/useAppThemeAndColorMode';
|
||||
import { DydxProvider } from '@/hooks/useDydxClient';
|
||||
import { DialogAreaProvider } from '@/hooks/useDialogArea';
|
||||
import { LocaleProvider } from '@/hooks/useLocaleSeparators';
|
||||
import { PotentialMarketsProvider } from '@/hooks/usePotentialMarkets';
|
||||
import { RestrictionProvider } from '@/hooks/useRestrictions';
|
||||
import { SubaccountProvider } from '@/hooks/useSubaccount';
|
||||
import { store } from '@/state/_store';
|
||||
|
||||
import { GlobalStyle } from '@/styles/globalStyle';
|
||||
|
||||
import { SelectMenu, SelectItem } from '@/components/SelectMenu';
|
||||
|
||||
import {
|
||||
AppTheme,
|
||||
AppThemeSystemSetting,
|
||||
AppColorMode,
|
||||
setAppThemeSetting,
|
||||
setAppColorMode,
|
||||
} from '@/state/configs';
|
||||
import { AppThemeProvider } from '@/hooks/useAppTheme';
|
||||
|
||||
import { setLocaleLoaded, setSelectedLocale } from '@/state/localization';
|
||||
import { store } from '@/state/_store';
|
||||
|
||||
import { config } from '@/lib/wagmi';
|
||||
import { AppTheme, setAppTheme } from '@/state/configs';
|
||||
import { setLocaleLoaded } from '@/state/localization';
|
||||
|
||||
import '@/index.css';
|
||||
import './ladle.css';
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
const wrapProvider = (Component: React.ComponentType<any>, props?: any) => {
|
||||
// eslint-disable-next-line react/display-name
|
||||
return ({ children }: { children: React.ReactNode }) => (
|
||||
<Component {...props}>{children}</Component>
|
||||
);
|
||||
};
|
||||
|
||||
const providers = [
|
||||
wrapProvider(QueryClientProvider, { client: queryClient }),
|
||||
wrapProvider(GrazProvider),
|
||||
wrapProvider(WagmiConfig, { config }),
|
||||
wrapProvider(LocaleProvider),
|
||||
wrapProvider(RestrictionProvider),
|
||||
wrapProvider(DydxProvider),
|
||||
wrapProvider(AccountsProvider),
|
||||
wrapProvider(SubaccountProvider),
|
||||
wrapProvider(DialogAreaProvider),
|
||||
wrapProvider(PotentialMarketsProvider),
|
||||
wrapProvider(AppThemeAndColorModeProvider),
|
||||
];
|
||||
|
||||
export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const [theme, setTheme] = useState(AppTheme.Classic);
|
||||
const [colorMode, setColorMode] = useState(AppColorMode.GreenUp);
|
||||
|
||||
useEffect(() => {
|
||||
store.dispatch(setAppThemeSetting(theme));
|
||||
store.dispatch(setAppColorMode(colorMode));
|
||||
}, [theme, colorMode]);
|
||||
store.dispatch(setAppTheme(theme));
|
||||
switch (theme) {
|
||||
case AppTheme.Dark: {
|
||||
document?.documentElement?.classList.remove('theme-light');
|
||||
document?.documentElement?.classList.add('theme-dark');
|
||||
break;
|
||||
}
|
||||
case AppTheme.Light: {
|
||||
document?.documentElement?.classList.remove('theme-dark');
|
||||
document?.documentElement?.classList.add('theme-light');
|
||||
break;
|
||||
}
|
||||
case AppTheme.Classic: {
|
||||
document?.documentElement?.classList.remove('theme-dark', 'theme-light');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, [theme]);
|
||||
|
||||
useEffect(() => {
|
||||
store.dispatch(setSelectedLocale({ locale: SupportedLocales.EN }));
|
||||
store.dispatch(setLocaleLoaded(true));
|
||||
}, []);
|
||||
|
||||
const content = [...providers].reverse().reduce(
|
||||
(children, Provider) => {
|
||||
return <Provider>{children}</Provider>;
|
||||
},
|
||||
<StoryContent>
|
||||
<GlobalStyle />
|
||||
{children}
|
||||
</StoryContent>
|
||||
);
|
||||
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<StoryHeader>
|
||||
<h4>Active Theme:</h4>
|
||||
<SelectMenu value={theme} onValueChange={setTheme}>
|
||||
<SelectMenu
|
||||
value={theme}
|
||||
onValueChange={setTheme}
|
||||
>
|
||||
{[
|
||||
{
|
||||
value: AppTheme.Classic,
|
||||
label: 'Default theme',
|
||||
},
|
||||
{
|
||||
value: AppThemeSystemSetting.System,
|
||||
label: 'System theme',
|
||||
},
|
||||
{
|
||||
value: AppTheme.Dark,
|
||||
label: 'Dark theme',
|
||||
@@ -107,28 +66,20 @@ export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children
|
||||
label: 'Light theme',
|
||||
},
|
||||
].map(({ value, label }) => (
|
||||
<SelectItem key={value} value={value} label={label} />
|
||||
))}
|
||||
</SelectMenu>
|
||||
<h4>Active Color Mode:</h4>
|
||||
<SelectMenu value={colorMode} onValueChange={setColorMode}>
|
||||
{[
|
||||
{
|
||||
value: AppColorMode.GreenUp,
|
||||
label: 'Green up',
|
||||
},
|
||||
{
|
||||
value: AppColorMode.RedUp,
|
||||
label: 'Red up',
|
||||
},
|
||||
].map(({ value, label }) => (
|
||||
<SelectItem key={value} value={value} label={label} />
|
||||
<SelectItem
|
||||
key={value}
|
||||
value={value}
|
||||
label={label}
|
||||
/>
|
||||
))}
|
||||
</SelectMenu>
|
||||
</StoryHeader>
|
||||
<hr />
|
||||
{content}
|
||||
</Provider>
|
||||
<AppThemeProvider>
|
||||
<GlobalStyle />
|
||||
<StoryContent>{children}</StoryContent>
|
||||
</AppThemeProvider>
|
||||
</Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -78,12 +78,11 @@ Set environment variables via `.env`.
|
||||
- `VITE_V3_TOKEN_ADDRESS` (optional): Address of the V3 $DYDX token.
|
||||
- `VITE_TOKEN_MIGRATION_URI` (optional): The URL of the token migration website.
|
||||
- `AMPLITUDE_API_KEY` (optional): Amplitude API key for enabling Amplitude; used with `pnpm run build:inject-amplitude`.
|
||||
- `AMPLITUDE_SERVER_URL` (optional): Custom Amplitude server URL
|
||||
- `BUGSNAG_API_KEY` (optional): API key for enabling Bugsnag; used with `pnpm run build:inject-bugsnag`.
|
||||
- `IOS_APP_ID` (optional): iOS app ID used for enabling deep linking to the iOS app; used with `pnpm run build:inject-app-deeplinks`.
|
||||
- `INTERCOM_APP_ID` (optional): Used for enabling Intercom; utilized with `pnpm run build:inject-intercom`.
|
||||
- `STATUS_PAGE_SCRIPT_URI` (optional): Used for enabling the status page; used with `pnpm run build:inject-statuspage`.
|
||||
- `SMARTBANNER_APP_NAME`, `SMARTBANNER_ORG_NAME`, `SMARTBANNER_ICON_URL`, `SMARTBANNER_APPSTORE_URL` (optional): Used for enabling the smart app banner; used with `pnpm run build:inject-smartbanner`.
|
||||
|
||||
|
||||
# Deployments
|
||||
|
||||
@@ -107,9 +106,6 @@ pnpm run build --mode testnet
|
||||
If you wish to incorporate analytics via Amplitude and Bugsnag, you can use our scripts:
|
||||
`pnpm run build:inject-amplitude` and `pnpm run build:inject-bugsnag`. You will need to provide your own API keys for these services. In the Environment Variables section, name the variables as `AMPLITUDE_API_KEY` and `BUGSNAG_API_KEY` and provide the respective keys as their values.
|
||||
|
||||
If you wish to incorporate smart banner for iOS and/or Android apps, you can use our scripts:
|
||||
`pnpm run build:inject-smartbanner`. You will need to provide your own app configurations for these services. In the Environment Variables section, name the variables as `SMARTBANNER_APP_NAME`, `SMARTBANNER_ORG_NAME`, `SMARTBANNER_ICON_URL` and `SMARTBANNER_APPSTORE_URL` or `SMARTBANNER_GOOGLEPLAY_URL` and provide the respective values.
|
||||
|
||||
For more details, check out Vercel's [official documentation](https://vercel.com/docs).
|
||||
|
||||
## Deploying to IPFS
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
"build:inject-bugsnag": "node scripts/inject-bugsnag.js",
|
||||
"build:inject-intercom": "node scripts/inject-intercom.js",
|
||||
"build:inject-statuspage": "node scripts/inject-statuspage.js",
|
||||
"build:inject-smartbanner": "node scripts/inject-smartbanner.js",
|
||||
"deploy:ipfs": "node scripts/upload-ipfs.js --verbose",
|
||||
"deploy:update-ipns": "node scripts/update-ipns.js",
|
||||
"deploy:update-dnslink": "node scripts/update-dnslink.js",
|
||||
@@ -40,9 +39,9 @@
|
||||
"@cosmjs/proto-signing": "^0.32.1",
|
||||
"@cosmjs/stargate": "^0.32.1",
|
||||
"@cosmjs/tendermint-rpc": "^0.32.1",
|
||||
"@dydxprotocol/v4-abacus": "^1.4.2",
|
||||
"@dydxprotocol/v4-client-js": "^1.0.20",
|
||||
"@dydxprotocol/v4-localization": "^1.1.26",
|
||||
"@dydxprotocol/v4-abacus": "^1.2.5",
|
||||
"@dydxprotocol/v4-client-js": "^1.0.14",
|
||||
"@dydxprotocol/v4-localization": "^1.1.11",
|
||||
"@ethersproject/providers": "^5.7.2",
|
||||
"@js-joda/core": "^5.5.3",
|
||||
"@radix-ui/react-accordion": "^1.1.2",
|
||||
@@ -93,7 +92,6 @@
|
||||
"buffer": "^6.0.3",
|
||||
"cmdk": "^0.2.0",
|
||||
"color": "^4.2.3",
|
||||
"cosmjs-types": "^0.9.0",
|
||||
"crypto-js": "^4.1.1",
|
||||
"ethers": "^6.6.1",
|
||||
"graz": "^0.0.43",
|
||||
@@ -118,7 +116,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.22.5",
|
||||
"@ladle/react": "^4.0.2",
|
||||
"@ladle/react": "^2.15.0",
|
||||
"@types/color": "^3.0.3",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/luxon": "^3.3.0",
|
||||
@@ -157,10 +155,5 @@
|
||||
"vitest": "^0.32.2",
|
||||
"w3name": "^1.0.8",
|
||||
"web3.storage": "^4.5.4"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"follow-redirects": "1.15.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
[
|
||||
{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "exchange.dydx.trading.debug",
|
||||
"sha256_cert_fingerprints": [
|
||||
"8A:9C:CC:49:B0:35:9A:91:67:CB:98:B0:B5:87:92:5F:9E:B7:EF:CE:A0:47:57:85:A4:35:3E:0C:E1:56:9E:A2"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "exchange.dydx.trading",
|
||||
"sha256_cert_fingerprints": [
|
||||
"B2:2D:CC:27:9D:52:05:98:63:C9:7B:34:36:70:A3:8E:00:31:28:08:2D:2E:70:76:C9:31:AE:F9:55:21:15:A5"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
After Width: | Height: | Size: 122 KiB |
@@ -1,19 +0,0 @@
|
||||
<svg width="120" height="97" viewBox="0 0 120 97" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect y="8" width="120" height="1" fill="currentColor"/>
|
||||
<rect y="18" width="120" height="1" fill="currentColor"/>
|
||||
<rect y="28" width="120" height="1" fill="currentColor"/>
|
||||
<rect y="38" width="120" height="1" fill="currentColor"/>
|
||||
<rect y="48" width="120" height="1" fill="currentColor"/>
|
||||
<rect y="58" width="120" height="1" fill="currentColor"/>
|
||||
<rect y="68" width="120" height="1" fill="currentColor"/>
|
||||
<rect y="78" width="120" height="1" fill="currentColor"/>
|
||||
<rect y="88" width="120" height="1" fill="currentColor"/>
|
||||
<rect x="18" width="1" height="97" fill="currentColor"/>
|
||||
<rect x="32" width="1" height="97" fill="currentColor"/>
|
||||
<rect x="46" width="1" height="97" fill="currentColor"/>
|
||||
<rect x="60" width="1" height="97" fill="currentColor"/>
|
||||
<rect x="74" width="1" height="97" fill="currentColor"/>
|
||||
<rect x="88" width="1" height="97" fill="currentColor"/>
|
||||
<rect x="102" width="1" height="97" fill="currentColor"/>
|
||||
<path d="M0 0H120V97H0V0Z" fill="url(#paint0_radial_314_37586)"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,20 +0,0 @@
|
||||
<svg width="90" height="39" viewBox="0 0 90 39" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect y="31.2344" width="2.57142" height="7.71427" fill="#3ED9A4"/>
|
||||
<rect x="5.14258" y="28.6648" width="2.57142" height="5.14284" fill="#E45555"/>
|
||||
<rect x="25.7139" y="26.0923" width="2.57142" height="10.2857" fill="#E45555"/>
|
||||
<rect x="51.4283" y="28.6648" width="2.57142" height="5.14284" fill="#E45555"/>
|
||||
<rect x="56.5712" y="31.2344" width="2.57142" height="5.14284" fill="#E45555"/>
|
||||
<rect x="77.1426" y="18.3767" width="2.57142" height="5.14284" fill="#E45555"/>
|
||||
<rect x="41.1427" y="23.5198" width="2.57142" height="5.14284" fill="#E45555"/>
|
||||
<rect x="10.2856" y="28.6648" width="2.57142" height="10.2857" fill="#3ED9A4"/>
|
||||
<rect x="61.7143" y="23.5198" width="2.57142" height="10.2857" fill="#3ED9A4"/>
|
||||
<rect x="66.8569" y="20.9492" width="2.57142" height="5.14284" fill="#3ED9A4"/>
|
||||
<rect x="71.9997" y="13.2346" width="2.57142" height="7.71427" fill="#3ED9A4"/>
|
||||
<rect x="82.2856" y="10.6631" width="2.57142" height="10.2857" fill="#3ED9A4"/>
|
||||
<rect x="87.4287" y="0.37793" width="2.57142" height="15.4285" fill="#3ED9A4"/>
|
||||
<rect x="15.4284" y="26.0923" width="2.57142" height="5.14284" fill="#3ED9A4"/>
|
||||
<rect x="20.5714" y="23.5198" width="2.57142" height="5.14284" fill="#3ED9A4"/>
|
||||
<rect x="30.857" y="31.2344" width="2.57142" height="5.14284" fill="#3ED9A4"/>
|
||||
<rect x="35.9999" y="26.0923" width="2.57142" height="5.14284" fill="#3ED9A4"/>
|
||||
<rect x="46.2853" y="26.0923" width="2.57142" height="2.57142" fill="#3ED9A4"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.2 MiB |
|
Before Width: | Height: | Size: 2.1 MiB |
@@ -11,13 +11,6 @@
|
||||
],
|
||||
"default": "dydxprotocol-mainnet"
|
||||
},
|
||||
"TESTFLIGHT": {
|
||||
"environments": [
|
||||
"dydxprotocol-mainnet",
|
||||
"dydxprotocol-testnet"
|
||||
],
|
||||
"default": "dydxprotocol-mainnet"
|
||||
},
|
||||
"TESTNET": {
|
||||
"environments": [
|
||||
"dydxprotocol-testnet"
|
||||
@@ -88,15 +81,14 @@
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"foundation": "https://www.dydx.foundation",
|
||||
"help": "https://help.dydx.exchange/",
|
||||
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
|
||||
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||
"documentation": "https://docs.dydx.exchange/",
|
||||
"community": "https://discord.com/invite/dydx",
|
||||
"governanceLearnMore": "https://help.dydx.exchange",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||
"stakingLearnMore": "https://help.dydx.exchange",
|
||||
"keplrDashboard": "https://testnet.keplr.app/",
|
||||
"strideZoneApp": "https://testnet.stride.zone",
|
||||
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
|
||||
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
|
||||
},
|
||||
@@ -117,16 +109,6 @@
|
||||
"images": "/wallets/",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX Chain"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": true
|
||||
}
|
||||
},
|
||||
"dydxprotocol-dev-2": {
|
||||
@@ -172,15 +154,14 @@
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"foundation": "https://www.dydx.foundation",
|
||||
"help": "https://help.dydx.exchange/",
|
||||
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
|
||||
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||
"documentation": "https://docs.dydx.exchange/",
|
||||
"community": "https://discord.com/invite/dydx",
|
||||
"governanceLearnMore": "https://help.dydx.exchange",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||
"stakingLearnMore": "https://help.dydx.exchange",
|
||||
"keplrDashboard": "https://testnet.keplr.app/",
|
||||
"strideZoneApp": "https://testnet.stride.zone",
|
||||
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
|
||||
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
|
||||
},
|
||||
@@ -201,16 +182,6 @@
|
||||
"images": "/wallets/",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX Chain"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": true
|
||||
}
|
||||
},
|
||||
"dydxprotocol-dev-4": {
|
||||
@@ -257,15 +228,14 @@
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"foundation": "https://www.dydx.foundation",
|
||||
"help": "https://help.dydx.exchange/",
|
||||
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
|
||||
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||
"documentation": "https://docs.dydx.exchange/",
|
||||
"community": "https://discord.com/invite/dydx",
|
||||
"governanceLearnMore": "https://help.dydx.exchange",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||
"stakingLearnMore": "https://help.dydx.exchange",
|
||||
"keplrDashboard": "https://testnet.keplr.app/",
|
||||
"strideZoneApp": "https://testnet.stride.zone",
|
||||
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
|
||||
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
|
||||
},
|
||||
@@ -286,16 +256,6 @@
|
||||
"images": "/wallets/",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX Chain"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": true
|
||||
}
|
||||
},
|
||||
"dydxprotocol-dev-5": {
|
||||
@@ -341,15 +301,14 @@
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"foundation": "https://www.dydx.foundation",
|
||||
"help": "https://help.dydx.exchange/",
|
||||
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
|
||||
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||
"documentation": "https://docs.dydx.exchange/",
|
||||
"community": "https://discord.com/invite/dydx",
|
||||
"governanceLearnMore": "https://help.dydx.exchange",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||
"stakingLearnMore": "https://help.dydx.exchange",
|
||||
"keplrDashboard": "https://testnet.keplr.app/",
|
||||
"strideZoneApp": "https://testnet.stride.zone",
|
||||
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
|
||||
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
|
||||
},
|
||||
@@ -370,16 +329,6 @@
|
||||
"images": "/wallets/",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX Chain"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": true
|
||||
}
|
||||
},
|
||||
"dydxprotocol-staging": {
|
||||
@@ -429,13 +378,12 @@
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"help": "https://help.dydx.exchange",
|
||||
"foundation": "https://www.dydx.foundation",
|
||||
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
|
||||
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||
"governanceLearnMore": "https://help.dydx.exchange",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||
"stakingLearnMore": "https://help.dydx.exchange",
|
||||
"keplrDashboard": "https://testnet.keplr.app/",
|
||||
"strideZoneApp": "https://testnet.stride.zone",
|
||||
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
|
||||
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
|
||||
},
|
||||
@@ -456,16 +404,6 @@
|
||||
"images": "/wallets/",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX Chain"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": true
|
||||
}
|
||||
},
|
||||
"dydxprotocol-staging-forced-update": {
|
||||
@@ -513,8 +451,7 @@
|
||||
"documentation": "https://v4-teacher.vercel.app/",
|
||||
"community": "https://discord.com/invite/dydx",
|
||||
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals"
|
||||
"blogs": "https://www.dydx.foundation/blog"
|
||||
},
|
||||
"wallets": {
|
||||
"walletconnect": {
|
||||
@@ -540,16 +477,6 @@
|
||||
"build": 40000,
|
||||
"url": "https://apps.apple.com/app/dydx/id1564787350"
|
||||
}
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": true
|
||||
}
|
||||
},
|
||||
"dydxprotocol-staging-west": {
|
||||
@@ -599,13 +526,12 @@
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"help": "https://help.dydx.exchange",
|
||||
"foundation": "https://www.dydx.foundation",
|
||||
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
|
||||
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||
"governanceLearnMore": "https://help.dydx.exchange",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||
"stakingLearnMore": "https://help.dydx.exchange",
|
||||
"keplrDashboard": "https://testnet.keplr.app/",
|
||||
"strideZoneApp": "https://testnet.stride.zone",
|
||||
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
|
||||
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
|
||||
},
|
||||
@@ -626,16 +552,6 @@
|
||||
"images": "/wallets/",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX Chain"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": true
|
||||
}
|
||||
},
|
||||
"dydxprotocol-testnet": {
|
||||
@@ -689,13 +605,12 @@
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"foundation": "https://www.dydx.foundation",
|
||||
"help": "https://help.dydx.exchange/",
|
||||
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
|
||||
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||
"governanceLearnMore": "https://help.dydx.exchange",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||
"stakingLearnMore": "https://help.dydx.exchange",
|
||||
"keplrDashboard": "https://testnet.keplr.app/",
|
||||
"strideZoneApp": "https://testnet.stride.zone",
|
||||
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
|
||||
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
|
||||
},
|
||||
@@ -716,16 +631,6 @@
|
||||
"images": "/wallets/",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX V4"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": false
|
||||
}
|
||||
},
|
||||
"dydxprotocol-testnet-dydx": {
|
||||
@@ -776,13 +681,12 @@
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"foundation": "https://www.dydx.foundation",
|
||||
"help": "https://help.dydx.exchange/",
|
||||
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
|
||||
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||
"governanceLearnMore": "https://help.dydx.exchange",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||
"stakingLearnMore": "https://help.dydx.exchange",
|
||||
"keplrDashboard": "https://testnet.keplr.app/",
|
||||
"strideZoneApp": "https://testnet.stride.zone",
|
||||
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
|
||||
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
|
||||
},
|
||||
@@ -803,16 +707,6 @@
|
||||
"images": "/wallets/",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX V4"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": false
|
||||
}
|
||||
},
|
||||
"dydxprotocol-testnet-nodefleet": {
|
||||
@@ -863,13 +757,12 @@
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"foundation": "https://www.dydx.foundation",
|
||||
"help": "https://help.dydx.exchange/",
|
||||
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
|
||||
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||
"governanceLearnMore": "https://help.dydx.exchange",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||
"stakingLearnMore": "https://help.dydx.exchange",
|
||||
"keplrDashboard": "https://testnet.keplr.app/",
|
||||
"strideZoneApp": "https://testnet.stride.zone",
|
||||
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
|
||||
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
|
||||
},
|
||||
@@ -890,16 +783,6 @@
|
||||
"images": "/wallets/",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX V4"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": false
|
||||
}
|
||||
},
|
||||
"dydxprotocol-testnet-kingnodes": {
|
||||
@@ -950,13 +833,12 @@
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"foundation": "https://www.dydx.foundation",
|
||||
"help": "https://help.dydx.exchange/",
|
||||
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
|
||||
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||
"governanceLearnMore": "https://help.dydx.exchange",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||
"stakingLearnMore": "https://help.dydx.exchange",
|
||||
"keplrDashboard": "https://testnet.keplr.app/",
|
||||
"strideZoneApp": "https://testnet.stride.zone",
|
||||
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
|
||||
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
|
||||
},
|
||||
@@ -977,16 +859,6 @@
|
||||
"images": "/wallets/",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX V4"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": false
|
||||
}
|
||||
},
|
||||
"dydxprotocol-testnet-liquify": {
|
||||
@@ -1037,13 +909,12 @@
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"foundation": "https://www.dydx.foundation",
|
||||
"help": "https://help.dydx.exchange/",
|
||||
"initialMarginFractionLearnMore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
|
||||
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||
"governanceLearnMore": "https://help.dydx.exchange",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||
"stakingLearnMore": "https://help.dydx.exchange",
|
||||
"keplrDashboard": "https://testnet.keplr.app/",
|
||||
"strideZoneApp": "https://testnet.stride.zone",
|
||||
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
|
||||
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet"
|
||||
},
|
||||
@@ -1064,16 +935,6 @@
|
||||
"images": "/wallets/",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX V4"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": false
|
||||
}
|
||||
},
|
||||
"dydxprotocol-testnet-polkachu": {
|
||||
@@ -1122,8 +983,7 @@
|
||||
"documentation": "https://docs.dydx.exchange/",
|
||||
"community": "https://discord.com/invite/dydx",
|
||||
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals"
|
||||
"blogs": "https://www.dydx.foundation/blog"
|
||||
},
|
||||
"wallets": {
|
||||
"walletconnect": {
|
||||
@@ -1142,16 +1002,6 @@
|
||||
"images": "/wallets/",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX V4"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": false
|
||||
}
|
||||
},
|
||||
"dydxprotocol-testnet-bware": {
|
||||
@@ -1202,13 +1052,12 @@
|
||||
"blogs": "https://www.dydx.foundation/blog",
|
||||
"foundation": "https://www.dydx.foundation",
|
||||
"help": "https://help.dydx.exchange/",
|
||||
"initialMarginFractionLearnmore": "https://help.dydx.exchange/articles/5232637-maximum-position-sizes",
|
||||
"reduceOnlyLearnmore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||
"governanceLearnmore": "https://help.dydx.exchange",
|
||||
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||
"stakingLearnmore": "https://help.dydx.exchange",
|
||||
"keplrDashboard": "https://testnet.keplr.app/",
|
||||
"strideZoneApp": "https://testnet.stride.zone",
|
||||
"accountExportLearnmore": "https://help.dydx.exchange",
|
||||
"walletLearnmore": "https://www.dydx.academy/video/defi-wallet"
|
||||
},
|
||||
@@ -1229,16 +1078,6 @@
|
||||
"images": "/wallets/",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX V4"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 10000000,
|
||||
"delayBlocks": 900,
|
||||
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": false
|
||||
}
|
||||
},
|
||||
"dydxprotocol-mainnet": {
|
||||
@@ -1287,15 +1126,14 @@
|
||||
"feedback": "[HTTP link to feedback form, can be null]",
|
||||
"blogs": "[HTTP link to blogs, can be null]",
|
||||
"foundation": "[HTTP link to foundation, can be null]",
|
||||
"initialMarginFractionLearnMore": "[HTTP link to initial margin fraction learn more, can be null]",
|
||||
"reduceOnlyLearnMore": "[HTTP link to reduce-only learn more, can be null]",
|
||||
"documentation": "[HTTP link to documentation, can be null]",
|
||||
"community": "[HTTP link to community, can be null]",
|
||||
"help": "[HTTP link to help page, can be null]",
|
||||
"governanceLearnMore": "[HTTP link to governance learn more, can be null]",
|
||||
"newMarketProposalLearnMore": "[HTTP link to new market proposal learn more, can be null]",
|
||||
"stakingLearnMore": "[HTTP link to staking learn more, can be null]",
|
||||
"keplrDashboard": "[HTTP link to keplr dashboard, can be null]",
|
||||
"strideZoneApp": "[HTTP link to stride zone app, can be null]",
|
||||
"accountExportLearnMore": "[HTTP link to account export learn more, can be null]",
|
||||
"walletLearnMore": "[HTTP link to wallet learn more, can be null]"
|
||||
},
|
||||
@@ -1316,16 +1154,6 @@
|
||||
"images": "[Relative URL for wallet images]",
|
||||
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||
"signTypedDataDomainName": "dYdX Chain"
|
||||
},
|
||||
"governance": {
|
||||
"newMarketProposal": {
|
||||
"initialDepositAmount": 0,
|
||||
"delayBlocks": 0,
|
||||
"newMarketsMethodology": "[URL to spreadsheet or document that explains methodology]"
|
||||
}
|
||||
},
|
||||
"featureFlags": {
|
||||
"reduceOnlySupported": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
[
|
||||
{
|
||||
"name": "coinbase",
|
||||
"label": "Coinbase",
|
||||
"icon": "/exchanges/coinbase.png",
|
||||
"depositType": "noble"
|
||||
}
|
||||
]
|
||||
@@ -69,13 +69,6 @@
|
||||
"whitepaperLink": "https://bitcoincash.org/",
|
||||
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/bitcoin-cash/"
|
||||
},
|
||||
"BONK-USD": {
|
||||
"name": "BONK COIN",
|
||||
"tags": [],
|
||||
"websiteLink": "https://bonkcoin.com/",
|
||||
"whitepaperLink": "https://bonkcoin.com/",
|
||||
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/bonk1/"
|
||||
},
|
||||
"BLUR-USD": {
|
||||
"name": "Blur",
|
||||
"tags": [],
|
||||
@@ -176,13 +169,6 @@
|
||||
"whitepaperLink": "https://dfinity.org/whitepaper.pdf",
|
||||
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/internet-computer/"
|
||||
},
|
||||
"JUP-USD": {
|
||||
"name": "Jupiter",
|
||||
"tags": ["Defi"],
|
||||
"websiteLink": "https://station.jup.ag/",
|
||||
"whitepaperLink": "https://station.jup.ag/blog/green-paper",
|
||||
"coinMarketCapsLink": "https://coinmarketcap.com/currencies/jupiter-ag/"
|
||||
},
|
||||
"LDO-USD": {
|
||||
"name": "Lido DAO",
|
||||
"tags": ["Defi"],
|
||||
|
||||
|
Before Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 9.6 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 -->
|
||||
|
Before Width: | Height: | Size: 12 KiB |
|
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`
|
||||
4. In your deploy scripts add `pnpm run build:inject-intercom` after your pnpm build / vite build command.
|
||||
5. If you are using with the Amplitude deployment scripts, your build command may look like the following: `pnpm build && pnpm run build:inject-amplitude && pnpm run build:inject-intercom`
|
||||
|
||||
### Smartbanner
|
||||
Smartbanner to show download links to iOS and/or Android native apps on mobile devices.
|
||||
|
||||
<b>To use with dydxprotocol/v4-web:</b>
|
||||
1. iOS app App Store link or Android app Google Play link.
|
||||
2. Add configurations in Github > Secrets and Variables > Actions as
|
||||
`SMARTBANNER_APP_NAME` for app name
|
||||
`SMARTBANNER_ORG_NAME` for organization name
|
||||
`SMARTBANNER_ICON_URL` for icon image
|
||||
`SMARTBANNER_APPSTORE_URL` for iOS App Store link
|
||||
`SMARTBANNER_GOOGLEPLAY_URL` for Android Google Play link
|
||||
3. In your deploy scripts add `pnpm run build:inject-smartbanner` after your pnpm build / vite build command.
|
||||
4. If you are using with the Amplitude deployment scripts, your build command may look like the following: `pnpm build && pnpm run build:inject-smartbanner`
|
||||
|
||||
@@ -3,13 +3,12 @@ import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const AMPLITUDE_API_KEY = process.env.AMPLITUDE_API_KEY;
|
||||
const AMPLITUDE_SERVER_URL = process.env.AMPLITUDE_SERVER_URL;
|
||||
|
||||
const currentPath = fileURLToPath(import.meta.url);
|
||||
const projectRoot = path.dirname(currentPath);
|
||||
const htmlFilePath = path.resolve(projectRoot, '../dist/index.html');
|
||||
|
||||
if (AMPLITUDE_API_KEY) {
|
||||
if(AMPLITUDE_API_KEY){
|
||||
try {
|
||||
const html = await fs.readFile(htmlFilePath, 'utf-8');
|
||||
|
||||
@@ -19,34 +18,8 @@ if (AMPLITUDE_API_KEY) {
|
||||
`;
|
||||
|
||||
const amplitudeListenerScript = `<script type="module">
|
||||
!(function () {
|
||||
var e = "${AMPLITUDE_API_KEY}";
|
||||
e &&
|
||||
(globalThis.amplitude.init(e${
|
||||
AMPLITUDE_SERVER_URL
|
||||
? `, undefined, {
|
||||
serverUrl: "${AMPLITUDE_SERVER_URL}"
|
||||
}`
|
||||
: ''
|
||||
}),
|
||||
globalThis.amplitude.setOptOut(!1),
|
||||
globalThis.addEventListener("dydx:track", function (e) {
|
||||
var t = e.detail.eventType,
|
||||
d = e.detail.eventData;
|
||||
globalThis.amplitude.track(t, d);
|
||||
}),
|
||||
globalThis.addEventListener("dydx:identify", function (e) {
|
||||
var t = e.detail.property,
|
||||
d = e.detail.propertyValue;
|
||||
if ("walletAddress" === t) globalThis.amplitude.setUserId(d);
|
||||
else {
|
||||
var i = new globalThis.amplitude.Identify();
|
||||
i.set(t, d), globalThis.amplitude.identify(i);
|
||||
}
|
||||
}),
|
||||
console.log("Amplitude enabled."));
|
||||
})();
|
||||
</script>`;
|
||||
!function(){var e="${AMPLITUDE_API_KEY}";e&&(globalThis.amplitude.init(e),globalThis.amplitude.setOptOut(!1),globalThis.addEventListener("dydx:track",function(e){var t=e.detail.eventType,d=e.detail.eventData;globalThis.amplitude.track(t,d)}),globalThis.addEventListener("dydx:identify",function(e){var t=e.detail.property,d=e.detail.propertyValue;if("walletAddress"===t)globalThis.amplitude.setUserId(d);else{var i=new globalThis.amplitude.Identify;i.set(t,d),globalThis.amplitude.identify(i)}}),console.log("Amplitude enabled."))}();
|
||||
</script>`;
|
||||
|
||||
const injectedHtml = html.replace(
|
||||
'<div id="root"></div>',
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { WagmiConfig } from 'wagmi';
|
||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||
import { GrazProvider } from 'graz';
|
||||
|
||||
import { AppRoute, DEFAULT_TRADE_ROUTE, MarketsRoute } from '@/constants/routes';
|
||||
import { AppRoute, DEFAULT_TRADE_ROUTE } from '@/constants/routes';
|
||||
|
||||
import {
|
||||
useBreakpoints,
|
||||
@@ -16,12 +16,11 @@ import {
|
||||
} from '@/hooks';
|
||||
import { DydxProvider } from '@/hooks/useDydxClient';
|
||||
import { AccountsProvider } from '@/hooks/useAccounts';
|
||||
import { AppThemeAndColorModeProvider } from '@/hooks/useAppThemeAndColorMode';
|
||||
import { AppThemeProvider } from '@/hooks/useAppTheme';
|
||||
import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
|
||||
import { LocaleProvider } from '@/hooks/useLocaleSeparators';
|
||||
import { NotificationsProvider } from '@/hooks/useNotifications';
|
||||
import { LocalNotificationsProvider } from '@/hooks/useLocalNotifications';
|
||||
import { PotentialMarketsProvider } from '@/hooks/usePotentialMarkets';
|
||||
import { RestrictionProvider } from '@/hooks/useRestrictions';
|
||||
import { SubaccountProvider } from '@/hooks/useSubaccount';
|
||||
|
||||
@@ -45,16 +44,15 @@ import '@/styles/constants.css';
|
||||
import '@/styles/fonts.css';
|
||||
import '@/styles/web3modal.css';
|
||||
|
||||
const NewMarket = lazy(() => import('@/pages/markets/NewMarket'));
|
||||
const MarketsPage = lazy(() => import('@/pages/markets/Markets'));
|
||||
const PortfolioPage = lazy(() => import('@/pages/portfolio/Portfolio'));
|
||||
const AlertsPage = lazy(() => import('@/pages/AlertsPage'));
|
||||
const ProfilePage = lazy(() => import('@/pages/Profile'));
|
||||
const SettingsPage = lazy(() => import('@/pages/settings/Settings'));
|
||||
const TradePage = lazy(() => import('@/pages/trade/Trade'));
|
||||
const RewardsPage = lazy(() => import('@/pages/rewards/RewardsPage'));
|
||||
const TermsOfUsePage = lazy(() => import('@/pages/TermsOfUsePage'));
|
||||
const PrivacyPolicyPage = lazy(() => import('@/pages/PrivacyPolicyPage'));
|
||||
const TokenPage = lazy(() => import('@/pages/token/Token'));
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
@@ -83,11 +81,8 @@ const Content = () => {
|
||||
<Route path={AppRoute.Trade} element={<TradePage />} />
|
||||
</Route>
|
||||
|
||||
<Route path={AppRoute.Markets}>
|
||||
<Route path={MarketsRoute.New} element={<NewMarket />} />
|
||||
<Route path={AppRoute.Markets} element={<MarketsPage />} />
|
||||
</Route>
|
||||
<Route path={`/${chainTokenLabel}/*`} element={<TokenPage />} />
|
||||
<Route path={AppRoute.Markets} element={<MarketsPage />} />
|
||||
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
|
||||
{isTablet && (
|
||||
<>
|
||||
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
||||
@@ -141,8 +136,7 @@ const providers = [
|
||||
wrapProvider(LocalNotificationsProvider),
|
||||
wrapProvider(NotificationsProvider),
|
||||
wrapProvider(DialogAreaProvider),
|
||||
wrapProvider(PotentialMarketsProvider),
|
||||
wrapProvider(AppThemeAndColorModeProvider),
|
||||
wrapProvider(AppThemeProvider),
|
||||
];
|
||||
|
||||
const App = () => {
|
||||
@@ -207,7 +201,6 @@ Styled.Content = styled.div<{ isShowingHeader: boolean; isShowingFooter: boolean
|
||||
|
||||
Styled.Main = styled.main`
|
||||
${layoutMixins.contentSectionAttached}
|
||||
box-shadow: none;
|
||||
|
||||
grid-area: Main;
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ Styled.Trigger = styled(Trigger)`
|
||||
&:hover {
|
||||
${Styled.Icon} {
|
||||
color: var(--color-text-2);
|
||||
filter: brightness(var(--hover-filter-base));
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,9 @@ const AlertContainer = styled.div<StyleProps>`
|
||||
case AlertType.Info: {
|
||||
return css`
|
||||
--alert-accent-color: var(--color-text-1);
|
||||
|
||||
--alert-default-background-opacity: 0.133; // Relative
|
||||
// --alert-background: var(--color-layer-6); // Absolute
|
||||
`;
|
||||
}
|
||||
case AlertType.Success: {
|
||||
|
||||
@@ -16,7 +16,6 @@ const assetIcons = {
|
||||
AVAX: '/currencies/avax.png',
|
||||
BCH: '/currencies/bch.png',
|
||||
BLUR: '/currencies/blur.png',
|
||||
BONK: '/currencies/bonk.png',
|
||||
BTC: '/currencies/btc.png',
|
||||
CELO: '/currencies/celo.png',
|
||||
COMP: '/currencies/comp.png',
|
||||
@@ -31,7 +30,6 @@ const assetIcons = {
|
||||
ETH: '/currencies/eth.png',
|
||||
FIL: '/currencies/fil.png',
|
||||
ICP: '/currencies/icp.png',
|
||||
JUP: '/currencies/jup.png',
|
||||
LDO: '/currencies/ldo.png',
|
||||
LINK: '/currencies/link.png',
|
||||
LTC: '/currencies/ltc.png',
|
||||
|
||||
@@ -134,8 +134,8 @@ const ButtonStyle = css<StyleProps>`
|
||||
|
||||
--button-textColor: var(--color-text-0);
|
||||
--button-backgroundColor: transparent;
|
||||
--button-active-filter: brightness(var(--active-filter));
|
||||
--button-hover-filter: brightness(var(--hover-filter-base));
|
||||
--button-active-filter: brightness(0.9);
|
||||
--button-hover-filter: brightness(1.1);
|
||||
--button-hover-textColor: var(--button-textColor);
|
||||
|
||||
--button-radius: 0.5em;
|
||||
|
||||
@@ -89,10 +89,9 @@ const buttonActionVariants = {
|
||||
--button-border: solid var(--border-width) var(--color-border);
|
||||
`,
|
||||
[ButtonAction.Primary]: css`
|
||||
--button-textColor: var(--color-text-button);
|
||||
--button-textColor: var(--color-text-2);
|
||||
--button-backgroundColor: var(--color-accent);
|
||||
--button-border: solid var(--border-width) var(--color-border-white);
|
||||
--button-hover-filter: brightness(var(--hover-filter-variant));
|
||||
`,
|
||||
|
||||
[ButtonAction.Secondary]: css`
|
||||
@@ -102,17 +101,15 @@ const buttonActionVariants = {
|
||||
`,
|
||||
|
||||
[ButtonAction.Create]: css`
|
||||
--button-textColor: var(--color-text-button);
|
||||
--button-backgroundColor: var(--color-green);
|
||||
--button-textColor: var(--color-text-2);
|
||||
--button-backgroundColor: var(--color-positive);
|
||||
--button-border: solid var(--border-width) var(--color-border-white);
|
||||
--button-hover-filter: brightness(var(--hover-filter-variant));
|
||||
`,
|
||||
|
||||
[ButtonAction.Destroy]: css`
|
||||
--button-textColor: var(--color-text-button);
|
||||
--button-backgroundColor: var(--color-red);
|
||||
--button-textColor: var(--color-text-2);
|
||||
--button-backgroundColor: var(--color-negative);
|
||||
--button-border: solid var(--border-width) var(--color-border-white);
|
||||
--button-hover-filter: brightness(var(--hover-filter-variant));
|
||||
`,
|
||||
|
||||
[ButtonAction.Navigation]: css`
|
||||
@@ -122,10 +119,9 @@ const buttonActionVariants = {
|
||||
`,
|
||||
|
||||
[ButtonAction.Reset]: css`
|
||||
--button-textColor: var(--color-red);
|
||||
--button-textColor: var(--color-negative);
|
||||
--button-backgroundColor: var(--color-layer-3);
|
||||
--button-border: solid var(--border-width) var(--color-border-red);
|
||||
--button-hover-filter: brightness(var(--hover-filter-variant));
|
||||
`,
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Checkbox, CheckboxProps } from '@/components/Checkbox';
|
||||
|
||||
import { StoryWrapper } from '.ladle/components';
|
||||
|
||||
export const CheckboxStory: Story<CheckboxProps> = (args) => {
|
||||
export const Checkboxes: Story<CheckboxProps> = (args) => {
|
||||
const [isChecked, setIsChecked] = useState(false);
|
||||
|
||||
return (
|
||||
@@ -21,12 +21,4 @@ export const CheckboxStory: Story<CheckboxProps> = (args) => {
|
||||
);
|
||||
};
|
||||
|
||||
CheckboxStory.args = {};
|
||||
|
||||
CheckboxStory.argTypes = {
|
||||
disabled: {
|
||||
options: [true, false],
|
||||
control: { type: 'select' },
|
||||
defaultValue: false,
|
||||
}
|
||||
}
|
||||
Checkboxes.args = {};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import styled, { css, type AnyStyledComponent } from 'styled-components';
|
||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
import { Root, Indicator } from '@radix-ui/react-checkbox';
|
||||
import { CheckIcon } from '@radix-ui/react-icons';
|
||||
|
||||
@@ -9,7 +9,6 @@ type ElementProps = {
|
||||
onCheckedChange: (checked: boolean) => void;
|
||||
id?: string;
|
||||
label?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
type StyleProps = {
|
||||
@@ -24,25 +23,14 @@ export const Checkbox: React.FC<CheckboxProps> = ({
|
||||
onCheckedChange,
|
||||
id,
|
||||
label,
|
||||
disabled,
|
||||
}) => (
|
||||
<Styled.Container>
|
||||
<Styled.Root
|
||||
className={className}
|
||||
checked={checked}
|
||||
disabled={disabled}
|
||||
onCheckedChange={onCheckedChange}
|
||||
id={id}
|
||||
>
|
||||
<Styled.Root className={className} checked={checked} onCheckedChange={onCheckedChange} id={id}>
|
||||
<Styled.Indicator>
|
||||
<CheckIcon />
|
||||
</Styled.Indicator>
|
||||
</Styled.Root>
|
||||
{label && (
|
||||
<Styled.Label disabled={disabled} htmlFor={id}>
|
||||
{label}
|
||||
</Styled.Label>
|
||||
)}
|
||||
{label && <label htmlFor={id}>{label}</label>}
|
||||
</Styled.Container>
|
||||
);
|
||||
|
||||
@@ -52,27 +40,25 @@ Styled.Container = styled.div`
|
||||
${layoutMixins.row}
|
||||
gap: 1ch;
|
||||
font: var(--font-small-book);
|
||||
|
||||
label {
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
|
||||
Styled.Root = styled(Root)`
|
||||
--checkbox-backgroundColor: var(--color-layer-0);
|
||||
--checkbox-borderColor: var(--color-border);
|
||||
|
||||
min-width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
|
||||
border-radius: 0.375rem;
|
||||
border: var(--border-width) solid var(--checkbox-borderColor);
|
||||
border: var(--border-width) solid var(--color-border);
|
||||
background-color: var(--checkbox-backgroundColor);
|
||||
|
||||
&[data-state='checked'] {
|
||||
--checkbox-backgroundColor: var(--color-accent);
|
||||
}
|
||||
|
||||
&[data-disabled] {
|
||||
cursor: not-allowed;
|
||||
--checkbox-backgroundColor: var(--color-layer-1);
|
||||
}
|
||||
`;
|
||||
|
||||
Styled.Indicator = styled(Indicator)`
|
||||
@@ -80,17 +66,5 @@ Styled.Indicator = styled(Indicator)`
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
color: var(--color-text-button);
|
||||
`;
|
||||
|
||||
Styled.Label = styled.label<{ disabled?: boolean }>`
|
||||
cursor: pointer;
|
||||
color: var(--color-text-2);
|
||||
|
||||
${({ disabled }) =>
|
||||
disabled &&
|
||||
css`
|
||||
cursor: not-allowed;
|
||||
color: var(--color-text-0);
|
||||
`}
|
||||
`;
|
||||
|
||||
@@ -50,11 +50,10 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
|
||||
label={title}
|
||||
// value={highlightedCommand}
|
||||
// onValueChange={setHighlightedCommand}
|
||||
filter={(value: string, search: string) =>
|
||||
value.replace(/ /g, '').toLowerCase().includes(search.replace(/ /g, '').toLowerCase())
|
||||
? 1
|
||||
: 0
|
||||
}
|
||||
filter={(value: string, search: string) => {
|
||||
if (value.replace(/ /g, '').includes(search.replace(/ /g, ''))) return 1;
|
||||
return 0;
|
||||
}}
|
||||
className={className}
|
||||
$withStickyLayout={withStickyLayout}
|
||||
>
|
||||
|
||||
@@ -6,7 +6,6 @@ import { layoutMixins } from '@/styles/layoutMixins';
|
||||
type ElementProps = {
|
||||
title: string;
|
||||
subtitle?: React.ReactNode;
|
||||
slotLeft?: React.ReactNode;
|
||||
slotRight?: React.ReactNode;
|
||||
};
|
||||
|
||||
@@ -17,16 +16,14 @@ type StyleProps = {
|
||||
export const ContentSectionHeader = ({
|
||||
title,
|
||||
subtitle,
|
||||
slotLeft,
|
||||
slotRight,
|
||||
className,
|
||||
}: ElementProps & StyleProps) => (
|
||||
<Styled.ContentSectionHeader className={className}>
|
||||
{slotLeft}
|
||||
<Styled.Header>
|
||||
<div>
|
||||
{title && <h3>{title}</h3>}
|
||||
{subtitle && <p>{subtitle}</p>}
|
||||
</Styled.Header>
|
||||
</div>
|
||||
{slotRight}
|
||||
</Styled.ContentSectionHeader>
|
||||
);
|
||||
@@ -43,15 +40,9 @@ Styled.ContentSectionHeader = styled.header<StyleProps>`
|
||||
|
||||
padding: 1rem var(--header-horizontal-padding);
|
||||
|
||||
@media ${breakpoints.tablet} {
|
||||
flex-wrap: wrap;
|
||||
--header-horizontal-padding: 1.25rem;
|
||||
> div {
|
||||
${layoutMixins.column}
|
||||
}
|
||||
`;
|
||||
|
||||
Styled.Header = styled.div`
|
||||
${layoutMixins.column}
|
||||
flex: 1;
|
||||
|
||||
h3 {
|
||||
color: var(--color-text-2);
|
||||
@@ -63,4 +54,9 @@ Styled.Header = styled.div`
|
||||
font: var(--font-small-book);
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
@media ${breakpoints.tablet} {
|
||||
flex-wrap: wrap;
|
||||
--header-horizontal-padding: 1.25rem;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -77,7 +77,7 @@ Styled.InlineRow = styled.div<{ copied: boolean }>`
|
||||
`
|
||||
: css`
|
||||
&:hover {
|
||||
filter: brightness(var(--hover-filter-base));
|
||||
filter: brightness(1.1);
|
||||
text-decoration: underline;
|
||||
}
|
||||
`}
|
||||
@@ -87,7 +87,7 @@ Styled.Icon = styled(Icon)<{ copied: boolean }>`
|
||||
${({ copied }) =>
|
||||
copied &&
|
||||
css`
|
||||
color: var(--color-success);
|
||||
color: var(--color-positive);
|
||||
`}
|
||||
`;
|
||||
|
||||
@@ -96,7 +96,7 @@ Styled.IconButton = styled(IconButton)<{ copied: boolean }>`
|
||||
copied &&
|
||||
css`
|
||||
svg {
|
||||
color: var(--color-success);
|
||||
color: var(--color-positive);
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
@@ -7,50 +7,35 @@ import { StoryWrapper } from '.ladle/components';
|
||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
|
||||
export const DetailsStory: Story<Parameters<typeof Details>[0]> = (args) => (
|
||||
export const DetailsStory: Story<Parameters<typeof Details>> = () => (
|
||||
<StoryWrapper>
|
||||
<Styled.Resizable>
|
||||
<Details {...args} />
|
||||
<Details
|
||||
items={[
|
||||
{
|
||||
key: 'item-1',
|
||||
label: 'Item 1',
|
||||
tooltip: 'leverage',
|
||||
value: 'Value 1',
|
||||
},
|
||||
{
|
||||
key: 'item-2',
|
||||
label: 'Really really really long item name 2',
|
||||
tooltip: 'liquidation-price',
|
||||
value: 'Value 2',
|
||||
},
|
||||
{
|
||||
key: 'item-3',
|
||||
label: 'Item 3',
|
||||
tooltip: 'realized-pnl',
|
||||
value: 'Value 3',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Styled.Resizable>
|
||||
</StoryWrapper>
|
||||
);
|
||||
|
||||
DetailsStory.args = {
|
||||
items: [
|
||||
{
|
||||
key: 'item-1',
|
||||
label: 'Item 1',
|
||||
tooltip: 'leverage',
|
||||
value: 'Value 1',
|
||||
},
|
||||
{
|
||||
key: 'item-2',
|
||||
label: 'Really really really long item name 2',
|
||||
tooltip: 'liquidation-price',
|
||||
value: 'Value 2',
|
||||
},
|
||||
{
|
||||
key: 'item-3',
|
||||
label: 'Item 3',
|
||||
tooltip: 'realized-pnl',
|
||||
value: 'Value 3',
|
||||
},
|
||||
],
|
||||
showSubitems: false,
|
||||
isLoading: false,
|
||||
withOverflow: false,
|
||||
withSeparators: false,
|
||||
};
|
||||
|
||||
DetailsStory.argTypes = {
|
||||
justifyItems: { options: ['start', 'end'], control: { type: 'select' }, defaultValue: 'start' },
|
||||
layout: {
|
||||
options: ['column', 'row', 'rowColumns', 'grid', 'stackColumn'],
|
||||
control: { type: 'select' },
|
||||
defaultValue: 'column',
|
||||
},
|
||||
};
|
||||
|
||||
const Styled: Record<string, AnyStyledComponent> = {};
|
||||
|
||||
Styled.Resizable = styled.section`
|
||||
|
||||
@@ -62,6 +62,6 @@ Styled.DiffArrowContainer = styled.span<DiffArrowProps>`
|
||||
`,
|
||||
down: css`
|
||||
transform: rotate(90deg);
|
||||
`,
|
||||
`
|
||||
}[direction || 'right'])}
|
||||
`;
|
||||
|
||||
@@ -75,7 +75,7 @@ Styled.DiffValue = styled.div<{ hasInvalidNewValue?: boolean }>`
|
||||
${({ hasInvalidNewValue }) =>
|
||||
hasInvalidNewValue &&
|
||||
css`
|
||||
color: var(--color-error);
|
||||
color: var(--color-negative);
|
||||
`}
|
||||
`;
|
||||
|
||||
|
||||
@@ -35,8 +35,8 @@ export const DropdownHeaderMenu = <MenuItemValue extends string>({
|
||||
<Root>
|
||||
<Styled.Trigger className={className} asChild>
|
||||
<div>
|
||||
{children}
|
||||
<Styled.DropdownIconButton iconName={IconName.Caret} isToggle />
|
||||
{children}
|
||||
<Styled.DropdownIconButton iconName={IconName.Caret} isToggle />
|
||||
</div>
|
||||
</Styled.Trigger>
|
||||
<Portal>
|
||||
@@ -87,7 +87,7 @@ Styled.Trigger = styled(Trigger)`
|
||||
outline: none;
|
||||
|
||||
:hover {
|
||||
filter: brightness(var(--hover-filter-base));
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@@ -4,43 +4,38 @@ import { DropdownMenu } from '@/components/DropdownMenu';
|
||||
|
||||
import { StoryWrapper } from '.ladle/components';
|
||||
|
||||
export const DropdownMenuStory: Story<Parameters<typeof DropdownMenu>[0]> = (args) => {
|
||||
export const DropdownMenuStory: Story<Parameters<typeof DropdownMenu>> = (args) => {
|
||||
const exampleItems = [
|
||||
{
|
||||
value: '1',
|
||||
label: 'Item 1',
|
||||
onSelect: () => alert('Item 1 action'),
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
label: 'Item 2',
|
||||
onSelect: () => alert('Item 2 action'),
|
||||
},
|
||||
{
|
||||
value: '3',
|
||||
label: 'Item 3',
|
||||
onSelect: () => alert('Item 3 action'),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<StoryWrapper>
|
||||
<DropdownMenu {...args}>
|
||||
<DropdownMenu
|
||||
{...args}
|
||||
items={exampleItems}
|
||||
>
|
||||
<span>Menu</span>
|
||||
</DropdownMenu>
|
||||
</StoryWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
DropdownMenuStory.args = {
|
||||
items: [
|
||||
{
|
||||
value: '0',
|
||||
label: 'Item 0',
|
||||
onSelect: () => alert('Item 0 action'),
|
||||
},
|
||||
{
|
||||
value: '1',
|
||||
label: 'Item 1 (accent)',
|
||||
onSelect: () => alert('Item 1 action'),
|
||||
highlightColor: 'accent',
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
label: 'Item 2 (create)',
|
||||
onSelect: () => alert('Item 2 action'),
|
||||
highlightColor: 'create',
|
||||
},
|
||||
{
|
||||
value: '3',
|
||||
label: 'Item 3 (destroy)',
|
||||
onSelect: () => alert('Item 3 action'),
|
||||
highlightColor: 'destroy',
|
||||
},
|
||||
],
|
||||
};
|
||||
DropdownMenuStory.args = {};
|
||||
|
||||
DropdownMenuStory.argTypes = {
|
||||
align: {
|
||||
|
||||
@@ -13,7 +13,7 @@ export type DropdownMenuItem<T> = {
|
||||
label: React.ReactNode;
|
||||
onSelect?: () => void;
|
||||
separator?: boolean;
|
||||
highlightColor?: 'accent' | 'create' | 'destroy';
|
||||
highlightColor?: 'accent' | 'positive' | 'negative';
|
||||
};
|
||||
|
||||
type StyleProps = {
|
||||
@@ -82,7 +82,7 @@ Styled.Separator = styled(Separator)`
|
||||
margin: 0.25rem 1rem;
|
||||
`;
|
||||
|
||||
Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'create' | 'destroy' }>`
|
||||
Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'positive' | 'negative' }>`
|
||||
${popoverMixins.item}
|
||||
--item-font-size: var(--dropdownMenu-item-font-size);
|
||||
${({ $highlightColor }) =>
|
||||
@@ -90,11 +90,11 @@ Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'create' | 'destroy' }>
|
||||
['accent']: `
|
||||
--item-highlighted-textColor: var(--color-accent);
|
||||
`,
|
||||
['create']: `
|
||||
--item-highlighted-textColor: var(--color-green);
|
||||
['positive']: `
|
||||
--item-highlighted-textColor: var(--color-positive);
|
||||
`,
|
||||
['destroy']: `
|
||||
--item-highlighted-textColor: var(--color-red);
|
||||
['negative']: `
|
||||
--item-highlighted-textColor: var(--color-negative);
|
||||
`,
|
||||
}[$highlightColor])}
|
||||
|
||||
|
||||
@@ -28,22 +28,21 @@ const exampleItems = [
|
||||
},
|
||||
];
|
||||
|
||||
export const DropdownSelectMenuStory: Story<
|
||||
Pick<Parameters<typeof DropdownSelectMenu>[0], 'items' | 'align' | 'sideOffset' | 'disabled'>
|
||||
> = (args) => {
|
||||
export const DropdownSelectMenuStory: Story<Parameters<typeof DropdownSelectMenu>> = (args) => {
|
||||
const [item, setItem] = useState(exampleItems[0].value);
|
||||
return (
|
||||
<StoryWrapper>
|
||||
<DropdownSelectMenu value={item} onValueChange={(value) => setItem(value)} {...args} />
|
||||
<DropdownSelectMenu
|
||||
items={exampleItems}
|
||||
value={item}
|
||||
onValueChange={(value) => setItem(value)}
|
||||
{...args}
|
||||
/>
|
||||
</StoryWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
DropdownSelectMenuStory.args = {
|
||||
items: exampleItems,
|
||||
sideOffset: 1,
|
||||
disabled: false,
|
||||
};
|
||||
DropdownSelectMenuStory.args = {};
|
||||
|
||||
DropdownSelectMenuStory.argTypes = {
|
||||
align: {
|
||||
|
||||
@@ -32,7 +32,7 @@ export const FormInput = forwardRef<HTMLInputElement, FormInputProps>(
|
||||
isValidationAttached={validationConfig?.attached}
|
||||
>
|
||||
<Styled.InputContainer hasSlotRight={!!slotRight}>
|
||||
<Styled.WithLabel label={label} inputID={id} disabled={otherProps?.disabled}>
|
||||
<Styled.WithLabel label={label} inputID={id}>
|
||||
<Input ref={ref} id={id} {...otherProps} />
|
||||
</Styled.WithLabel>
|
||||
{slotRight}
|
||||
@@ -85,11 +85,11 @@ Styled.InputContainer = styled.div<{ hasSlotRight?: boolean }>`
|
||||
`}
|
||||
`;
|
||||
|
||||
Styled.WithLabel = styled(WithLabel)<{ disabled?: boolean }>`
|
||||
Styled.WithLabel = styled(WithLabel)`
|
||||
${formMixins.inputLabel}
|
||||
|
||||
label {
|
||||
${({ disabled }) => !disabled && 'cursor: text;'}
|
||||
cursor: text;
|
||||
padding: var(--form-input-paddingY) var(--form-input-paddingX) 0;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Icon, IconName } from '@/components/Icon';
|
||||
|
||||
import { StoryWrapper } from '.ladle/components';
|
||||
|
||||
export const IconStory: Story<Parameters<typeof Icon>[0]> = (args) => {
|
||||
export const IconStory: Story<Parameters<typeof Icon>> = (args) => {
|
||||
return (
|
||||
<StoryWrapper>
|
||||
<Icon {...args} />
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
CaretIcon,
|
||||
CautionCircleStrokeIcon,
|
||||
CautionCircleIcon,
|
||||
ChaosLabsIcon,
|
||||
ChatIcon,
|
||||
CheckIcon,
|
||||
CheckCircleIcon,
|
||||
@@ -25,7 +24,6 @@ import {
|
||||
CoinsIcon,
|
||||
CommentIcon,
|
||||
CopyIcon,
|
||||
CurrencySignIcon,
|
||||
DepositIcon,
|
||||
DepthChartIcon,
|
||||
DiscordIcon,
|
||||
@@ -36,7 +34,6 @@ import {
|
||||
FundingChartIcon,
|
||||
GearIcon,
|
||||
GiftboxIcon,
|
||||
GovernanceIcon,
|
||||
HelpCircleIcon,
|
||||
HideIcon,
|
||||
HistoryIcon,
|
||||
@@ -72,7 +69,6 @@ import {
|
||||
StarIcon,
|
||||
SunIcon,
|
||||
TerminalIcon,
|
||||
TokenIcon,
|
||||
TradeIcon,
|
||||
TransferIcon,
|
||||
TriangleIcon,
|
||||
@@ -94,7 +90,6 @@ export enum IconName {
|
||||
Caret = 'Caret',
|
||||
CautionCircle = 'CautionCircle',
|
||||
CautionCircleStroked = 'CautionCircleStroked',
|
||||
ChaosLabs = 'ChaosLabs',
|
||||
Chat = 'Chat',
|
||||
Check = 'Check',
|
||||
CheckCircle = 'CheckCircle',
|
||||
@@ -106,7 +101,6 @@ export enum IconName {
|
||||
Coins = 'Coins',
|
||||
Comment = 'Comment',
|
||||
Copy = 'Copy',
|
||||
CurrencySign = 'CurrencySign',
|
||||
Deposit = 'Deposit',
|
||||
DepthChart = 'DepthChart',
|
||||
Discord = 'Discord',
|
||||
@@ -117,7 +111,6 @@ export enum IconName {
|
||||
FundingChart = 'FundingChart',
|
||||
Gear = 'Gear',
|
||||
Giftbox = 'Giftbox',
|
||||
Governance = 'Governance',
|
||||
HelpCircle = 'HelpCircle',
|
||||
Hide = 'Hide',
|
||||
History = 'History',
|
||||
@@ -154,7 +147,6 @@ export enum IconName {
|
||||
Sun = 'Sun',
|
||||
Terminal = 'Terminal',
|
||||
TogglesMenu = 'TogglesMenu',
|
||||
Token = 'Token',
|
||||
Trade = 'Trade',
|
||||
Transfer = 'Transfer',
|
||||
Triangle = 'Triangle',
|
||||
@@ -176,7 +168,6 @@ const icons = {
|
||||
[IconName.Caret]: CaretIcon,
|
||||
[IconName.CautionCircle]: CautionCircleIcon,
|
||||
[IconName.CautionCircleStroked]: CautionCircleStrokeIcon,
|
||||
[IconName.ChaosLabs]: ChaosLabsIcon,
|
||||
[IconName.Chat]: ChatIcon,
|
||||
[IconName.Check]: CheckIcon,
|
||||
[IconName.CheckCircle]: CheckCircleIcon,
|
||||
@@ -188,7 +179,6 @@ const icons = {
|
||||
[IconName.Coins]: CoinsIcon,
|
||||
[IconName.Comment]: CommentIcon,
|
||||
[IconName.Copy]: CopyIcon,
|
||||
[IconName.CurrencySign]: CurrencySignIcon,
|
||||
[IconName.Deposit]: DepositIcon,
|
||||
[IconName.DepthChart]: DepthChartIcon,
|
||||
[IconName.Discord]: DiscordIcon,
|
||||
@@ -199,7 +189,6 @@ const icons = {
|
||||
[IconName.FundingChart]: FundingChartIcon,
|
||||
[IconName.Gear]: GearIcon,
|
||||
[IconName.Giftbox]: GiftboxIcon,
|
||||
[IconName.Governance]: GovernanceIcon,
|
||||
[IconName.HelpCircle]: HelpCircleIcon,
|
||||
[IconName.Hide]: HideIcon,
|
||||
[IconName.History]: HistoryIcon,
|
||||
@@ -235,7 +224,6 @@ const icons = {
|
||||
[IconName.Sun]: SunIcon,
|
||||
[IconName.Terminal]: TerminalIcon,
|
||||
[IconName.TogglesMenu]: TogglesMenuIcon,
|
||||
[IconName.Token]: TokenIcon,
|
||||
[IconName.Trade]: TradeIcon,
|
||||
[IconName.Transfer]: TransferIcon,
|
||||
[IconName.Triangle]: TriangleIcon,
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Link } from '@/components/Link';
|
||||
import { StoryWrapper } from '.ladle/components';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
|
||||
export const LinkStory: Story<Parameters<typeof Link>[0]> = (args) => {
|
||||
export const LinkStory: Story<Parameters<typeof Link>> = (args) => {
|
||||
return (
|
||||
<StoryWrapper>
|
||||
<Styled.Container>
|
||||
|
||||
@@ -11,7 +11,6 @@ export const LoadingSpinner: React.FC<{
|
||||
return (
|
||||
<Styled.Spinner className={className}>
|
||||
<Styled.LoadingSpinnerSvg
|
||||
id={id}
|
||||
width="38"
|
||||
height="38"
|
||||
viewBox="0 0 38 38"
|
||||
|
||||
@@ -5,24 +5,8 @@ import { HashRouter } from 'react-router-dom';
|
||||
|
||||
import { StoryWrapper } from '.ladle/components';
|
||||
|
||||
export const NavigationMenuStory: Story<
|
||||
Pick<Parameters<typeof NavigationMenu>[0], 'items' | 'orientation' | 'submenuPlacement'>
|
||||
> = (args) => {
|
||||
return (
|
||||
<StoryWrapper>
|
||||
<HashRouter
|
||||
children={
|
||||
<NavigationMenu {...args}>
|
||||
<span>Menu</span>
|
||||
</NavigationMenu>
|
||||
}
|
||||
/>
|
||||
</StoryWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
NavigationMenuStory.args = {
|
||||
items: [
|
||||
export const NavigationMenuStory: Story<Parameters<typeof NavigationMenu>> = (args) => {
|
||||
const exampleItems = [
|
||||
{
|
||||
group: 'navigation',
|
||||
groupLabel: 'Views',
|
||||
@@ -109,9 +93,23 @@ NavigationMenuStory.args = {
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
return (
|
||||
<StoryWrapper>
|
||||
<HashRouter
|
||||
children={
|
||||
<NavigationMenu {...args} items={exampleItems}>
|
||||
<span>Menu</span>
|
||||
</NavigationMenu>
|
||||
}
|
||||
/>
|
||||
</StoryWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
NavigationMenuStory.args = {};
|
||||
|
||||
NavigationMenuStory.argTypes = {
|
||||
orientation: {
|
||||
options: ['vertical', 'horizontal'],
|
||||
|
||||
@@ -65,9 +65,6 @@ type ElementProps = {
|
||||
resolution?: number;
|
||||
stripRelativeWords?: boolean;
|
||||
};
|
||||
timeOptions?: {
|
||||
useUTC?: boolean;
|
||||
};
|
||||
tag?: React.ReactNode;
|
||||
withParentheses?: boolean;
|
||||
locale?: string;
|
||||
@@ -92,7 +89,6 @@ export const Output = ({
|
||||
relativeTimeFormatOptions = {
|
||||
format: 'singleCharacter',
|
||||
},
|
||||
timeOptions,
|
||||
tag,
|
||||
withParentheses,
|
||||
locale = navigator.language || 'en-US',
|
||||
@@ -120,7 +116,6 @@ export const Output = ({
|
||||
{value?.toString() ?? null}
|
||||
|
||||
{tag && <Tag>{tag}</Tag>}
|
||||
{slotRight}
|
||||
</Styled.Text>
|
||||
);
|
||||
}
|
||||
@@ -170,21 +165,16 @@ export const Output = ({
|
||||
if ((typeof value !== 'string' && typeof value !== 'number') || !value) return null;
|
||||
const date = new Date(value);
|
||||
const dateString = {
|
||||
[OutputType.Date]: date.toLocaleString(selectedLocale, {
|
||||
dateStyle: 'medium',
|
||||
timeZone: timeOptions?.useUTC ? 'UTC' : undefined,
|
||||
}),
|
||||
[OutputType.Date]: date.toLocaleString(selectedLocale, { dateStyle: 'medium' }),
|
||||
[OutputType.DateTime]: date.toLocaleString(selectedLocale, {
|
||||
dateStyle: 'short',
|
||||
timeStyle: 'short',
|
||||
timeZone: timeOptions?.useUTC ? 'UTC' : undefined,
|
||||
}),
|
||||
[OutputType.Time]: date.toLocaleString(selectedLocale, {
|
||||
hour12: false,
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
timeZone: timeOptions?.useUTC ? 'UTC' : undefined,
|
||||
}),
|
||||
}[type];
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { Story } from '@ladle/react';
|
||||
|
||||
import { Panel, PanelProps } from '@/components/Panel';
|
||||
import { Panel } from '@/components/Panel';
|
||||
|
||||
import { StoryWrapper } from '.ladle/components';
|
||||
|
||||
export const PanelStory: Story<PanelProps> = (args) => {
|
||||
export const PanelStory: Story<{ slotHeader: React.ReactNode, children?: React.ReactNode }> = (args) => {
|
||||
return (
|
||||
<StoryWrapper>
|
||||
<Panel {...args} />
|
||||
@@ -13,8 +13,6 @@ export const PanelStory: Story<PanelProps> = (args) => {
|
||||
};
|
||||
|
||||
PanelStory.args = {
|
||||
slotHeaderContent: 'Header',
|
||||
slotHeader: 'Header',
|
||||
children: 'Content',
|
||||
slotRight: '1️⃣',
|
||||
hasSeparator: true,
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Icon, IconName } from '@/components/Icon';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
import { breakpoints } from '@/styles';
|
||||
|
||||
type ElementProps = {
|
||||
type PanelProps = {
|
||||
slotHeaderContent?: React.ReactNode;
|
||||
slotHeader?: React.ReactNode;
|
||||
slotRight?: React.ReactNode;
|
||||
@@ -16,13 +16,11 @@ type ElementProps = {
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
type StyleProps = {
|
||||
type PanelStyleProps = {
|
||||
className?: string;
|
||||
hasSeparator?: boolean;
|
||||
};
|
||||
|
||||
export type PanelProps = ElementProps & StyleProps;
|
||||
|
||||
export const Panel = ({
|
||||
slotHeaderContent,
|
||||
slotHeader,
|
||||
@@ -33,7 +31,7 @@ export const Panel = ({
|
||||
onClick,
|
||||
hasSeparator,
|
||||
className,
|
||||
}: PanelProps) => (
|
||||
}: PanelProps & PanelStyleProps) => (
|
||||
<Styled.Panel onClick={onClick} className={className}>
|
||||
<Styled.Left>
|
||||
{href ? (
|
||||
|
||||
@@ -11,7 +11,6 @@ type ElementProps = {
|
||||
};
|
||||
|
||||
type StyleProps = {
|
||||
className?: string;
|
||||
hasLogo?: boolean;
|
||||
size?: number;
|
||||
};
|
||||
@@ -19,7 +18,7 @@ type StyleProps = {
|
||||
const DARK_LOGO_MARK_URL = '/logos/logo-mark-dark.svg';
|
||||
const LIGHT_LOGO_MARK_URL = '/logos/logo-mark-light.svg';
|
||||
|
||||
export const QrCode = ({ className, value, hasLogo, size = 300 }: ElementProps & StyleProps) => {
|
||||
export const QrCode = ({ value, hasLogo, size = 300 }: ElementProps & StyleProps) => {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const appTheme: AppTheme = useSelector(getAppTheme);
|
||||
|
||||
@@ -75,7 +74,7 @@ export const QrCode = ({ className, value, hasLogo, size = 300 }: ElementProps &
|
||||
}
|
||||
}, [appTheme, hasLogo]);
|
||||
|
||||
return <Styled.QrCode className={className} ref={ref} />;
|
||||
return <Styled.QrCode ref={ref} />;
|
||||
};
|
||||
|
||||
const Styled: Record<string, AnyStyledComponent> = {};
|
||||
|
||||
@@ -7,7 +7,7 @@ import { StoryWrapper } from '.ladle/components';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
import { InputType } from './Input';
|
||||
|
||||
export const SearchInputStory: Story<Parameters<typeof SearchInput>[0]> = (args) => (
|
||||
export const SearchInputStory: Story<Parameters<typeof SearchInput>> = (args) => (
|
||||
<StoryWrapper>
|
||||
<Styled.Container>
|
||||
<SearchInput placeholder="Search something..." type={InputType.Search} />
|
||||
|
||||
@@ -6,7 +6,7 @@ import { SearchSelectMenu } from '@/components/SearchSelectMenu';
|
||||
|
||||
import { StoryWrapper } from '.ladle/components';
|
||||
|
||||
export const SearchSelectMenuStory: Story<Parameters<typeof SearchSelectMenu>[0]> = (args) => {
|
||||
export const SearchSelectMenuStory: Story<Parameters<typeof SearchSelectMenu>> = (args) => {
|
||||
const [selectedItem, setSelectedItem] = useState<string>();
|
||||
|
||||
const exampleItems = [
|
||||
@@ -24,7 +24,10 @@ export const SearchSelectMenuStory: Story<Parameters<typeof SearchSelectMenu>[0]
|
||||
return (
|
||||
<StoryWrapper>
|
||||
<Container>
|
||||
<SearchSelectMenu {...args} items={exampleItems}>
|
||||
<SearchSelectMenu
|
||||
{...args}
|
||||
items={exampleItems}
|
||||
>
|
||||
{!selectedItem ? <span>Search and Select</span> : <span>{selectedItem}</span>}
|
||||
</SearchSelectMenu>
|
||||
</Container>
|
||||
|
||||
@@ -26,7 +26,7 @@ const exampleItems: { value: string; label: string }[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const SelectMenuStory: Story<Parameters<typeof SelectMenu>[0]> = (args) => {
|
||||
export const SelectMenuStory: Story<Parameters<typeof SelectMenu>> = (args) => {
|
||||
const [value, setValue] = useState(exampleItems[0].value);
|
||||
const [value2, setValue2] = useState(exampleItems[2].value);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -68,7 +68,7 @@ export type TableItem<TableRowData> = {
|
||||
onSelect?: (key: TableRowData) => void;
|
||||
};
|
||||
|
||||
export type ColumnDef<TableRowData extends object> = {
|
||||
type ColumnDef<TableRowData extends object> = {
|
||||
columnKey: string;
|
||||
label: React.ReactNode;
|
||||
tag?: React.ReactNode;
|
||||
@@ -95,10 +95,7 @@ export type ElementProps<TableRowData extends object | CustomRowConfig, TableRow
|
||||
selectionBehavior?: 'replace' | 'toggle';
|
||||
onRowAction?: (key: TableRowKey, row: TableRowData) => void;
|
||||
slotEmpty?: React.ReactNode;
|
||||
viewMoreConfig?: {
|
||||
initialNumRowsToShow: number;
|
||||
numRowsPerPage?: number;
|
||||
};
|
||||
initialNumRowsToShow?: number;
|
||||
// collection: TableCollection<string>;
|
||||
// children: React.ReactNode;
|
||||
};
|
||||
@@ -128,7 +125,7 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
|
||||
selectionMode = 'single',
|
||||
selectionBehavior = 'toggle',
|
||||
slotEmpty,
|
||||
viewMoreConfig,
|
||||
initialNumRowsToShow = data.length,
|
||||
// shouldRowRender,
|
||||
|
||||
// collection,
|
||||
@@ -144,18 +141,7 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
|
||||
style,
|
||||
}: ElementProps<TableRowData, TableRowKey> & StyleProps) => {
|
||||
const [selectedKeys, setSelectedKeys] = useState(new Set<TableRowKey>());
|
||||
const [numRowsToShow, setNumRowsToShow] = useState(viewMoreConfig?.initialNumRowsToShow);
|
||||
const enableViewMore = viewMoreConfig !== undefined;
|
||||
|
||||
const onViewMoreClick = () => {
|
||||
if (!viewMoreConfig) return;
|
||||
const { numRowsPerPage } = viewMoreConfig;
|
||||
if (numRowsPerPage) {
|
||||
setNumRowsToShow((prev) => (prev ?? 0) + numRowsPerPage);
|
||||
} else {
|
||||
setNumRowsToShow(data.length);
|
||||
}
|
||||
};
|
||||
const [numRowsToShow, setNumRowsToShow] = useState(initialNumRowsToShow);
|
||||
|
||||
const currentBreakpoints = useBreakpoints();
|
||||
const shownColumns = columns.filter(
|
||||
@@ -231,7 +217,9 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
|
||||
}
|
||||
numColumns={shownColumns.length}
|
||||
onViewMoreClick={
|
||||
enableViewMore && numRowsToShow! < data.length ? onViewMoreClick : undefined
|
||||
numRowsToShow !== undefined && numRowsToShow < data.length
|
||||
? () => setNumRowsToShow(data.length)
|
||||
: undefined
|
||||
}
|
||||
// shouldRowRender={shouldRowRender}
|
||||
hideHeader={hideHeader}
|
||||
@@ -257,7 +245,7 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
|
||||
)}
|
||||
</TableHeader>
|
||||
|
||||
<TableBody items={enableViewMore ? list.items.slice(0, numRowsToShow) : list.items}>
|
||||
<TableBody items={list.items.slice(0, numRowsToShow)}>
|
||||
{(item) => (
|
||||
<Row key={getRowKey(item)}>
|
||||
{(columnKey) => (
|
||||
@@ -524,7 +512,7 @@ const TableColumnHeader = <TableRowData extends object>({
|
||||
export const ViewMoreRow = ({ colSpan, onClick }: { colSpan: number; onClick: () => void }) => {
|
||||
const stringGetter = useStringGetter();
|
||||
return (
|
||||
<Styled.ViewMoreTr key="viewmore">
|
||||
<Styled.Tr key="viewmore">
|
||||
<Styled.Td
|
||||
colSpan={colSpan}
|
||||
onMouseDown={(e: MouseEvent) => e.preventDefault()}
|
||||
@@ -534,7 +522,7 @@ export const ViewMoreRow = ({ colSpan, onClick }: { colSpan: number; onClick: ()
|
||||
{stringGetter({ key: STRING_KEYS.VIEW_MORE })}
|
||||
</Styled.ViewMoreButton>
|
||||
</Styled.Td>
|
||||
</Styled.ViewMoreTr>
|
||||
</Styled.Tr>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -684,8 +672,6 @@ Styled.TableWrapper = styled.div<{
|
||||
--table-lastColumn-cell-align: end; // start | center | end | var(--table-cell-align)
|
||||
--tableCell-padding: 0 1rem;
|
||||
|
||||
--tableViewMore-borderColor: inherit;
|
||||
|
||||
// Rules
|
||||
|
||||
flex: 1;
|
||||
@@ -795,7 +781,7 @@ Styled.Tr = styled.tr<{
|
||||
&:focus-visible,
|
||||
&:focus-within {
|
||||
--tableRow-currentBackgroundColor: var(--tableRow-hover-backgroundColor);
|
||||
filter: brightness(var(--hover-filter-base));
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
`};
|
||||
|
||||
@@ -996,8 +982,4 @@ Styled.ViewMoreButton = styled(Button)`
|
||||
width: 0.675rem;
|
||||
margin-left: 0.5ch;
|
||||
}
|
||||
`;
|
||||
|
||||
Styled.ViewMoreTr = styled(Styled.Tr)`
|
||||
--border-color: var(--tableViewMore-borderColor);
|
||||
`;
|
||||
`;
|
||||
@@ -13,11 +13,29 @@ enum TabItem {
|
||||
Item3 = 'Item3',
|
||||
}
|
||||
|
||||
export const TabsStory: Story<Parameters<typeof Tabs>[0]> = (args) => {
|
||||
const TabItems = [
|
||||
{
|
||||
value: TabItem.Item1,
|
||||
label: 'Item 1',
|
||||
content: <div>Item 1 Content</div>,
|
||||
},
|
||||
{
|
||||
value: TabItem.Item2,
|
||||
label: 'Item 2',
|
||||
content: <div>Item 2 Content</div>,
|
||||
},
|
||||
{
|
||||
value: TabItem.Item3,
|
||||
label: 'Item 3',
|
||||
content: <div>Item 3 Content</div>,
|
||||
},
|
||||
];
|
||||
|
||||
export const TabsStory: Story<Parameters<typeof Tabs>> = (args) => {
|
||||
return (
|
||||
<StoryWrapper>
|
||||
<Styled.Container>
|
||||
<Tabs {...args} />
|
||||
<Tabs items={TabItems} {...args} />
|
||||
</Styled.Container>
|
||||
</StoryWrapper>
|
||||
);
|
||||
@@ -25,23 +43,6 @@ export const TabsStory: Story<Parameters<typeof Tabs>[0]> = (args) => {
|
||||
|
||||
TabsStory.args = {
|
||||
fullWidthTabs: false,
|
||||
items: [
|
||||
{
|
||||
value: TabItem.Item1,
|
||||
label: 'Item 1',
|
||||
content: <div>Item 1 Content</div>,
|
||||
},
|
||||
{
|
||||
value: TabItem.Item2,
|
||||
label: 'Item 2',
|
||||
content: <div>Item 2 Content</div>,
|
||||
},
|
||||
{
|
||||
value: TabItem.Item3,
|
||||
label: 'Item 3',
|
||||
content: <div>Item 3 Content</div>,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
TabsStory.argTypes = {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { Story } from '@ladle/react';
|
||||
|
||||
import { Tag, TagSign, TagSize, TagType } from '@/components/Tag';
|
||||
import { Tag } from '@/components/Tag';
|
||||
|
||||
import { StoryWrapper } from '.ladle/components';
|
||||
|
||||
export const TagStory: Story<Parameters<typeof Tag>[0]> = (args) => {
|
||||
export const TagStory: Story<Parameters<typeof Tag>> = (args) => {
|
||||
return (
|
||||
<StoryWrapper>
|
||||
<Tag {...args} />
|
||||
@@ -14,23 +14,4 @@ export const TagStory: Story<Parameters<typeof Tag>[0]> = (args) => {
|
||||
|
||||
TagStory.args = {
|
||||
children: 'USDC',
|
||||
isHighlighted: false,
|
||||
};
|
||||
|
||||
TagStory.argTypes = {
|
||||
size: {
|
||||
options: Object.values(TagSize),
|
||||
control: { type: 'select' },
|
||||
defaultValue: TagSize.Small,
|
||||
},
|
||||
type: {
|
||||
options: [...Object.values(TagType), undefined],
|
||||
control: { type: 'select' },
|
||||
defaultValue: undefined,
|
||||
},
|
||||
sign: {
|
||||
options: [...Object.values(TagSign), undefined],
|
||||
control: { type: 'select' },
|
||||
defaultValue: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import styled, { css } from 'styled-components';
|
||||
|
||||
export enum TagSize {
|
||||
Small = 'Small',
|
||||
Medium = 'Medium',
|
||||
Small,
|
||||
Medium,
|
||||
}
|
||||
|
||||
export enum TagType {
|
||||
Asset = 'Asset',
|
||||
Side = 'Side',
|
||||
Number = 'Number',
|
||||
Asset,
|
||||
Side,
|
||||
Number,
|
||||
}
|
||||
|
||||
export enum TagSign {
|
||||
Positive = 'Positive',
|
||||
Negative = 'Negative',
|
||||
Neutral = 'Neutral',
|
||||
Positive,
|
||||
Negative,
|
||||
Neutral,
|
||||
}
|
||||
|
||||
type StyleProps = {
|
||||
|
||||
@@ -8,7 +8,6 @@ import { Button, type ButtonStateConfig, type ButtonProps } from '@/components/B
|
||||
|
||||
type ElementProps = {
|
||||
timeoutInSeconds: number;
|
||||
slotFinal?: ReactNode;
|
||||
} & ButtonProps;
|
||||
|
||||
export type TimeoutButtonProps = ElementProps;
|
||||
@@ -16,7 +15,6 @@ export type TimeoutButtonProps = ElementProps;
|
||||
export const TimeoutButton = ({
|
||||
children,
|
||||
timeoutInSeconds,
|
||||
slotFinal,
|
||||
...otherProps
|
||||
}: TimeoutButtonProps) => {
|
||||
const [timeoutDeadline] = useState(Date.now() + timeoutInSeconds * 1000);
|
||||
@@ -25,8 +23,6 @@ export const TimeoutButton = ({
|
||||
|
||||
const secondsLeft = Math.max(0, (timeoutDeadline - now) / 1000);
|
||||
|
||||
if (slotFinal && secondsLeft <= 0) return slotFinal;
|
||||
|
||||
return (
|
||||
<Button
|
||||
{...otherProps}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ButtonShape, ButtonSize } from '@/constants/buttons';
|
||||
import { StoryWrapper } from '.ladle/components';
|
||||
import { ToggleButton } from './ToggleButton';
|
||||
|
||||
export const ToggleButtonStory: Story<Parameters<typeof ToggleButton>[0]> = (args) => (
|
||||
export const ToggleButtonStory: Story<Parameters<typeof ToggleButton>> = (args) => (
|
||||
<StoryWrapper>
|
||||
<ToggleButton {...args}>Toggle me</ToggleButton>
|
||||
</StoryWrapper>
|
||||
|
||||
@@ -21,22 +21,16 @@ const ToggleGroupItems = [
|
||||
},
|
||||
];
|
||||
|
||||
export const ToggleGroupStory: Story<
|
||||
Pick<Parameters<typeof ToggleGroup>[0], 'items' | 'size' | 'shape'>
|
||||
> = (args) => {
|
||||
export const ToggleGroupStory: Story<Parameters<typeof ToggleGroup>> = (args) => {
|
||||
const [value, setValue] = useState('0');
|
||||
|
||||
return (
|
||||
<StoryWrapper>
|
||||
<ToggleGroup value={value} onValueChange={setValue} {...args} />
|
||||
<ToggleGroup items={ToggleGroupItems} value={value} onValueChange={setValue} {...args} />
|
||||
</StoryWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
ToggleGroupStory.args = {
|
||||
items: ToggleGroupItems,
|
||||
};
|
||||
|
||||
ToggleGroupStory.argTypes = {
|
||||
size: {
|
||||
options: Object.values(ButtonSize),
|
||||
|
||||
@@ -117,7 +117,7 @@ Styled.ConfirmButton = styled(Styled.IconButton)`
|
||||
--button-backgroundColor: hsla(203, 25%, 19%, 1);
|
||||
|
||||
svg {
|
||||
color: var(--color-green);
|
||||
color: var(--color-positive);
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -125,7 +125,7 @@ Styled.CancelButton = styled(Styled.IconButton)`
|
||||
--button-backgroundColor: hsla(296, 16%, 18%, 1);
|
||||
|
||||
svg {
|
||||
color: var(--color-red);
|
||||
color: var(--color-negative);
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
|
||||
|
||||
@@ -40,5 +40,5 @@ Styled.Details = styled(Details)`
|
||||
|
||||
padding: 0.375rem 0.75rem 0.25rem;
|
||||
|
||||
font-size: var(--details-item-fontSize, 0.8125em);
|
||||
font-size: 0.8125em;
|
||||
`;
|
||||
|
||||
@@ -9,7 +9,7 @@ import { StoryWrapper } from '.ladle/components';
|
||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
|
||||
export const WithLabelStory: Story<Parameters<typeof WithLabel>[0]> = (args) => {
|
||||
export const WithLabelStory: Story<Parameters<typeof WithLabel>> = (args) => {
|
||||
const [firstName, setFirstName] = useState('');
|
||||
const [lastName, setLastName] = useState('');
|
||||
|
||||
|
||||
@@ -3,29 +3,32 @@ import type { Story } from '@ladle/react';
|
||||
import { Button } from '@/components/Button';
|
||||
|
||||
import { WithReceipt } from '@/components/WithReceipt';
|
||||
import { type DetailsItem } from './Details';
|
||||
|
||||
import { StoryWrapper } from '.ladle/components';
|
||||
|
||||
export const WithReceiptStory: Story<Omit<Parameters<typeof WithReceipt>[0], 'slotReceipt'>> = (
|
||||
args
|
||||
) => (
|
||||
const items: DetailsItem[] = [
|
||||
{
|
||||
key: 'item-1',
|
||||
label: 'Item 1',
|
||||
value: 'Value 1',
|
||||
},
|
||||
{
|
||||
key: 'item-2',
|
||||
label: 'Item 2',
|
||||
value: 'Value 2',
|
||||
},
|
||||
{
|
||||
key: 'item-3',
|
||||
label: 'Item 3',
|
||||
value: 'Value 3',
|
||||
},
|
||||
];
|
||||
|
||||
export const WithReceiptStory: Story<Parameters<WithReceipt>> = (args) => (
|
||||
<StoryWrapper>
|
||||
<div style={{ width: 200 }}>
|
||||
<WithReceipt
|
||||
slotReceipt={
|
||||
<div
|
||||
style={{
|
||||
padding: '1rem',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
Receipt Content
|
||||
</div>
|
||||
}
|
||||
{...args}
|
||||
>
|
||||
<WithReceipt {...args}>
|
||||
<Button>Hello there</Button>
|
||||
</WithReceipt>
|
||||
</div>
|
||||
@@ -33,7 +36,7 @@ export const WithReceiptStory: Story<Omit<Parameters<typeof WithReceipt>[0], 'sl
|
||||
);
|
||||
|
||||
WithReceiptStory.args = {
|
||||
hideReceipt: false,
|
||||
items,
|
||||
};
|
||||
|
||||
WithReceiptStory.argTypes = {
|
||||
|
||||
@@ -106,6 +106,8 @@ Styled.Container = styled.div`
|
||||
--stickyArea1-leftGap: var(--border-width);
|
||||
min-height: var(--stickyArea-height);
|
||||
|
||||
${layoutMixins.withOuterAndInnerBorders}
|
||||
|
||||
display: grid;
|
||||
grid-template: var(--withSidebar-gridTemplate);
|
||||
`;
|
||||
@@ -118,7 +120,6 @@ Styled.Side = styled.aside`
|
||||
${layoutMixins.sticky}
|
||||
max-height: var(--stickyArea-height);
|
||||
backdrop-filter: none;
|
||||
background-color: var(--color-layer-2);
|
||||
|
||||
${layoutMixins.stack}
|
||||
`;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { tooltipStrings } from '@/constants/tooltips';
|
||||
|
||||
import { StoryWrapper } from '.ladle/components';
|
||||
|
||||
export const Tooltip: Story<Parameters<typeof WithTooltip>[0]> = (args) => {
|
||||
export const Tooltip: Story<Parameters<typeof WithTooltip>> = (args) => {
|
||||
return (
|
||||
<StoryWrapper>
|
||||
<WithTooltip {...args}>
|
||||
|
||||
@@ -119,13 +119,6 @@ export const InputSelectionOption = Abacus.exchange.dydx.abacus.output.input.Sel
|
||||
// ------ Wallet ------ //
|
||||
export type Wallet = Abacus.exchange.dydx.abacus.output.Wallet;
|
||||
export type AccountBalance = Abacus.exchange.dydx.abacus.output.AccountBalance;
|
||||
export type TradingRewards = Abacus.exchange.dydx.abacus.output.TradingRewards;
|
||||
export type HistoricalTradingReward = Abacus.exchange.dydx.abacus.output.HistoricalTradingReward;
|
||||
export const HistoricalTradingRewardsPeriod =
|
||||
Abacus.exchange.dydx.abacus.state.manager.HistoricalTradingRewardsPeriod;
|
||||
const historicalTradingRewardsPeriod = [...HistoricalTradingRewardsPeriod.values()] as const;
|
||||
export type HistoricalTradingRewardsPeriods = (typeof historicalTradingRewardsPeriod)[number];
|
||||
|
||||
export type Subaccount = Abacus.exchange.dydx.abacus.output.Subaccount;
|
||||
export type SubaccountPosition = Abacus.exchange.dydx.abacus.output.SubaccountPosition;
|
||||
export type SubaccountOrder = Abacus.exchange.dydx.abacus.output.SubaccountOrder;
|
||||
@@ -209,9 +202,6 @@ export const RestrictionType = Abacus.exchange.dydx.abacus.output.Restriction;
|
||||
const restrictionTypes = [...RestrictionType.values()] as const;
|
||||
export type RestrictionTypes = (typeof restrictionTypes)[number];
|
||||
|
||||
// ------ Api data ------ //
|
||||
export const ApiData = Abacus.exchange.dydx.abacus.state.manager.ApiData;
|
||||
|
||||
// ------ Enum Conversions ------ //
|
||||
type IfEquals<X, Y, A, B> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2
|
||||
? A
|
||||
@@ -246,15 +236,6 @@ export const HISTORICAL_PNL_PERIODS: Record<
|
||||
[HistoricalPnlPeriod.Period90d.name]: HistoricalPnlPeriod.Period90d,
|
||||
};
|
||||
|
||||
export const HISTORICAL_TRADING_REWARDS_PERIODS: Record<
|
||||
KotlinIrEnumValues<typeof HistoricalTradingRewardsPeriod>,
|
||||
HistoricalTradingRewardsPeriods
|
||||
> = {
|
||||
[HistoricalTradingRewardsPeriod.MONTHLY.name]: HistoricalTradingRewardsPeriod.MONTHLY,
|
||||
[HistoricalTradingRewardsPeriod.WEEKLY.name]: HistoricalTradingRewardsPeriod.WEEKLY,
|
||||
[HistoricalTradingRewardsPeriod.DAILY.name]: HistoricalTradingRewardsPeriod.DAILY,
|
||||
};
|
||||
|
||||
export const ORDER_STATUS_STRINGS: Record<KotlinIrEnumValues<typeof AbacusOrderStatus>, string> = {
|
||||
[AbacusOrderStatus.open.name]: STRING_KEYS.OPEN_STATUS,
|
||||
[AbacusOrderStatus.open.rawValue]: STRING_KEYS.OPEN_STATUS,
|
||||
|
||||
@@ -173,5 +173,3 @@ export type AnalyticsEventData<T extends AnalyticsEvent> =
|
||||
validatorUrl: string;
|
||||
}
|
||||
: never;
|
||||
|
||||
export const DEFAULT_TRANSACTION_MEMO = 'dYdX Frontend (web)';
|
||||
|
||||
@@ -2,10 +2,8 @@ export enum DialogTypes {
|
||||
ClosePosition = 'ClosePosition',
|
||||
Deposit = 'Deposit',
|
||||
DisconnectWallet = 'DisconnectWallet',
|
||||
DisplaySettings = 'DisplaySettings',
|
||||
ExchangeOffline = 'ExchangeOffline',
|
||||
ExternalLink = 'ExternalLink',
|
||||
ExternalNavStride = 'ExternalNavStride',
|
||||
FillDetails = 'FillDetails',
|
||||
Help = 'Help',
|
||||
ExternalNavKeplr = 'ExternalNavKeplr',
|
||||
@@ -21,8 +19,6 @@ export enum DialogTypes {
|
||||
Transfer = 'Transfer',
|
||||
Withdraw = 'Withdraw',
|
||||
ManageFunds = 'ManageFunds',
|
||||
NewMarketMessageDetails = 'NewMarketMessageDetails',
|
||||
NewMarketAgreement = 'NewMarketAgreement',
|
||||
}
|
||||
|
||||
export enum TradeBoxDialogTypes {
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
* Temporary Indexer types
|
||||
* remove when Indexer type lib is available through @dydxprotocol/v4-client-js
|
||||
*/
|
||||
export type PerpetualMarketResponse = {
|
||||
clobPairId: string;
|
||||
ticker: string;
|
||||
status: string;
|
||||
oraclePrice: string;
|
||||
priceChange24H: string;
|
||||
volume24H: string;
|
||||
trades24H: number;
|
||||
nextFundingRate: string;
|
||||
initialMarginFraction: string;
|
||||
maintenanceMarginFraction: string;
|
||||
openInterest: string;
|
||||
atomicResolution: number;
|
||||
quantumConversionExponent: number;
|
||||
tickSize: string;
|
||||
stepSize: string;
|
||||
stepBaseQuantums: number;
|
||||
subticksPerTick: number;
|
||||
};
|
||||
@@ -20,7 +20,6 @@ export enum LocalStorageKey {
|
||||
SelectedLocale = 'dydx.SelectedLocale',
|
||||
SelectedNetwork = 'dydx.SelectedNetwork',
|
||||
SelectedTheme = 'dydx.SelectedTheme',
|
||||
SelectedColorMode = 'dydx.SelectedColorMode',
|
||||
SelectedTradeLayout = 'dydx.SelectedTradeLayout',
|
||||
TradingViewChartConfig = 'dydx.TradingViewChartConfig',
|
||||
HasSeenLaunchIncentives = 'dydx.HasSeenLaunchIncentives',
|
||||
|
||||
@@ -95,7 +95,7 @@ export type TooltipStrings = {
|
||||
stringParams?: any;
|
||||
urlConfigs?: LinksConfigs;
|
||||
}) => {
|
||||
title?: string;
|
||||
title: string;
|
||||
body: string;
|
||||
learnMoreLink?: string;
|
||||
};
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
export type ExchangeConfigItem = {
|
||||
exchangeName: string;
|
||||
ticker: string;
|
||||
adjustByMarket?: string;
|
||||
};
|
||||
|
||||
export type PotentialMarketItem = {
|
||||
baseAsset: string;
|
||||
referencePrice: string;
|
||||
numOracles: number;
|
||||
liquidityTier: number;
|
||||
assetName: string;
|
||||
p: number;
|
||||
atomicResolution: number;
|
||||
minExchanges: number;
|
||||
minPriceChangePpm: number;
|
||||
priceExponent: number;
|
||||
stepBaseQuantum: number;
|
||||
ticksizeExponent: number;
|
||||
subticksPerTick: number;
|
||||
minOrderSize: number;
|
||||
quantumConversionExponent: number;
|
||||
};
|
||||
|
||||
export const NUM_ORACLES_TO_QUALIFY_AS_SAFE = 6;
|
||||
@@ -11,10 +11,6 @@ export enum AppRoute {
|
||||
Privacy = '/privacy',
|
||||
}
|
||||
|
||||
export enum MarketsRoute {
|
||||
New = 'new',
|
||||
}
|
||||
|
||||
export enum PortfolioRoute {
|
||||
Fees = 'fees',
|
||||
History = 'history',
|
||||
@@ -29,12 +25,6 @@ export enum HistoryRoute {
|
||||
Payments = 'payments',
|
||||
}
|
||||
|
||||
export enum TokenRoute {
|
||||
TradingRewards = 'trading-rewards',
|
||||
StakingRewards = 'staking-rewards',
|
||||
Governance = 'governance',
|
||||
}
|
||||
|
||||
export enum MobileSettingsRoute {
|
||||
Language = 'language',
|
||||
Notifications = 'notifications',
|
||||
|
||||
@@ -68,9 +68,3 @@ export enum OpacityToken {
|
||||
Opacity66 = 'A8',
|
||||
Opacity90 = 'E6',
|
||||
}
|
||||
|
||||
export enum BrightnessFilterToken {
|
||||
Darken10 = '0.9',
|
||||
Darken5 = '0.95',
|
||||
Lighten10 = '1.1',
|
||||
}
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
import { AppColorMode } from '@/state/configs';
|
||||
|
||||
export type Theme = {
|
||||
[AppColorMode.GreenUp]: ThemeColorBase;
|
||||
[AppColorMode.RedUp]: ThemeColorBase;
|
||||
};
|
||||
|
||||
export type ThemeColorBase = BaseColors &
|
||||
LayerColors &
|
||||
export type ThemeColors = LayerColors &
|
||||
BorderColors &
|
||||
TextColors &
|
||||
GradientColors &
|
||||
@@ -15,14 +7,7 @@ export type ThemeColorBase = BaseColors &
|
||||
DirectionalColors &
|
||||
RiskColors &
|
||||
IconColors &
|
||||
ComponentColors &
|
||||
Filters;
|
||||
|
||||
type BaseColors = {
|
||||
white: string;
|
||||
green: string;
|
||||
red: string;
|
||||
};
|
||||
ComponentColors;
|
||||
|
||||
type LayerColors = {
|
||||
layer0: string;
|
||||
@@ -45,8 +30,6 @@ type TextColors = {
|
||||
textPrimary: string;
|
||||
textSecondary: string;
|
||||
textTertiary: string;
|
||||
|
||||
textButton: string;
|
||||
};
|
||||
|
||||
type GradientColors = {
|
||||
@@ -64,13 +47,8 @@ type StatusColors = {
|
||||
success: string;
|
||||
warning: string;
|
||||
error: string;
|
||||
successFaded: string;
|
||||
warningFaded: string;
|
||||
errorFaded: string;
|
||||
};
|
||||
|
||||
/** ##InvertDirectionalColors
|
||||
* When adding colors here, make sure to update linked function to invert colors for AppColorMode. */
|
||||
type DirectionalColors = {
|
||||
positive: string;
|
||||
negative: string;
|
||||
@@ -93,12 +71,7 @@ type IconColors = {
|
||||
type ComponentColors = {
|
||||
inputBackground: string;
|
||||
popoverBackground: string;
|
||||
switchThumbActiveBackground: string;
|
||||
toggleBackground: string;
|
||||
tooltipBackground: string;
|
||||
};
|
||||
|
||||
type Filters = {
|
||||
hoverFilterBase: string;
|
||||
hoverFilterVariant: string;
|
||||
activeFilter: string;
|
||||
};
|
||||
|
||||
@@ -57,9 +57,10 @@ export const tradeTooltips: TooltipStrings = {
|
||||
title: stringGetter({ key: TOOLTIP_STRING_KEYS.INDEX_PRICE_TITLE }),
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.INDEX_PRICE_BODY }),
|
||||
}),
|
||||
'initial-margin-fraction': ({ stringGetter }) => ({
|
||||
'initial-margin-fraction': ({ stringGetter, urlConfigs }) => ({
|
||||
title: stringGetter({ key: TOOLTIP_STRING_KEYS.INITIAL_MARGIN_FRACTION_TITLE }),
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.INITIAL_MARGIN_FRACTION_BODY }),
|
||||
learnMoreLink: urlConfigs?.initialMarginFractionLearnMore,
|
||||
}),
|
||||
'initial-stop': ({ stringGetter }) => ({
|
||||
title: stringGetter({ key: TOOLTIP_STRING_KEYS.INITIAL_STOP_TITLE }),
|
||||
@@ -137,10 +138,6 @@ export const tradeTooltips: TooltipStrings = {
|
||||
title: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_TITLE }),
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_BODY }),
|
||||
}),
|
||||
'post-only-timeinforce-gtt': ({ stringGetter }) => ({
|
||||
title: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_TIMEINFORCE_GTT_TITLE }),
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_TIMEINFORCE_GTT_BODY }),
|
||||
}),
|
||||
'price-impact': ({ stringGetter }) => ({
|
||||
title: stringGetter({ key: TOOLTIP_STRING_KEYS.PRICE_IMPACT_TITLE }),
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.PRICE_IMPACT_BODY }),
|
||||
@@ -154,18 +151,6 @@ export const tradeTooltips: TooltipStrings = {
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_BODY }),
|
||||
learnMoreLink: urlConfigs?.reduceOnlyLearnMore,
|
||||
}),
|
||||
'reduce-only-execution-ioc-fok': ({ stringGetter }) => ({
|
||||
title: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_EXECUTION_IOC_FOK_TITLE }),
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_EXECUTION_IOC_FOK_BODY }),
|
||||
}),
|
||||
'reduce-only-timeinforce-ioc-fok': ({ stringGetter }) => ({
|
||||
title: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_TIMEINFORCE_IOC_FOK_TITLE }),
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_TIMEINFORCE_IOC_FOK_BODY }),
|
||||
}),
|
||||
'reference-price': ({ stringGetter }) => ({
|
||||
title: stringGetter({ key: TOOLTIP_STRING_KEYS.REFERENCE_PRICE_TITLE }),
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REFERENCE_PRICE_BODY }),
|
||||
}),
|
||||
spread: () => ({
|
||||
title: 'Spread',
|
||||
body: 'The difference in price between the highest bid (the price a buyer is willing to buy for) and lowest ask (the price a seller is willing to sell for) an asset.',
|
||||
@@ -198,7 +183,4 @@ export const tradeTooltips: TooltipStrings = {
|
||||
title: stringGetter({ key: TOOLTIP_STRING_KEYS.UNREALIZED_PNL_TITLE }),
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.UNREALIZED_PNL_BODY }),
|
||||
}),
|
||||
'reward-history': ({ stringGetter }) => ({
|
||||
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REWARD_HISTORY_BODY }),
|
||||
}),
|
||||
} as const;
|
||||
|
||||
@@ -33,14 +33,12 @@ export enum WalletConnectionType {
|
||||
CosmosSigner = 'CosmosSigner',
|
||||
InjectedEip1193 = 'injectedEip1193',
|
||||
WalletConnect2 = 'walletConnect2',
|
||||
TestWallet = 'TestWallet',
|
||||
}
|
||||
|
||||
export enum WalletErrorType {
|
||||
// General
|
||||
ChainMismatch,
|
||||
UserCanceled,
|
||||
SwitchChainMethodMissing,
|
||||
|
||||
// Non-Deterministic
|
||||
NonDeterministicWallet,
|
||||
@@ -70,9 +68,6 @@ export const walletConnectionTypes: Record<WalletConnectionType, WalletConnectio
|
||||
[WalletConnectionType.CosmosSigner]: {
|
||||
name: 'CosmosSigner',
|
||||
},
|
||||
[WalletConnectionType.TestWallet]: {
|
||||
name: 'TestWallet',
|
||||
},
|
||||
};
|
||||
|
||||
// Wallets
|
||||
@@ -93,7 +88,7 @@ export enum WalletType {
|
||||
TokenPocket = 'TOKEN_POCKET',
|
||||
TrustWallet = 'TRUST_WALLET',
|
||||
WalletConnect2 = 'WALLETCONNECT_2',
|
||||
TestWallet = 'TEST_WALLET',
|
||||
// TestWallet = 'TEST_WALLET',
|
||||
OtherWallet = 'OTHER_WALLET',
|
||||
}
|
||||
|
||||
@@ -248,12 +243,6 @@ export const wallets: Record<WalletType, WalletConfig> = {
|
||||
icon: KeplrIcon,
|
||||
connectionTypes: [WalletConnectionType.CosmosSigner],
|
||||
},
|
||||
[WalletType.TestWallet]: {
|
||||
type: WalletType.TestWallet,
|
||||
stringKey: STRING_KEYS.TEST_WALLET,
|
||||
icon: GenericWalletIcon,
|
||||
connectionTypes: [WalletConnectionType.TestWallet],
|
||||
},
|
||||
};
|
||||
|
||||
// Injected EIP-1193 Providers
|
||||
@@ -365,5 +354,3 @@ export enum DydxChainAsset {
|
||||
USDC = 'usdc',
|
||||
CHAINTOKEN = 'chain',
|
||||
}
|
||||
|
||||
export const TEST_WALLET_EVM_ADDRESS: EvmAddress = '0x0000000000000000000000000000000000000000';
|
||||
|
||||
@@ -12,9 +12,8 @@ import {
|
||||
ORDERBOOK_WIDTH,
|
||||
} from '@/constants/orderbook';
|
||||
|
||||
import { useAppThemeAndColorModeContext } from '@/hooks/useAppThemeAndColorMode';
|
||||
|
||||
import { getCurrentMarketConfig, getCurrentMarketOrderbookMap } from '@/state/perpetualsSelectors';
|
||||
import { getAppTheme } from '@/state/configsSelectors';
|
||||
|
||||
import { MustBigNumber } from '@/lib/numbers';
|
||||
|
||||
@@ -24,6 +23,7 @@ import {
|
||||
getXByColumn,
|
||||
getYForElements,
|
||||
} from '@/lib/orderbookHelpers';
|
||||
import { useAppThemeContext } from '../useAppTheme';
|
||||
|
||||
type ElementProps = {
|
||||
data: Array<PerpetualMarketOrderbookLevel | undefined>;
|
||||
@@ -53,7 +53,7 @@ export const useDrawOrderbook = ({
|
||||
const { stepSizeDecimals = TOKEN_DECIMALS, tickSizeDecimals = SMALL_USD_DECIMALS } =
|
||||
useSelector(getCurrentMarketConfig, shallowEqual) || {};
|
||||
const prevData = useRef<typeof data>(data);
|
||||
const theme = useAppThemeAndColorModeContext();
|
||||
const theme = useAppThemeContext();
|
||||
|
||||
/**
|
||||
* Scale canvas using device pixel ratio to unblur drawn text
|
||||
|
||||
@@ -7,7 +7,6 @@ import { useDebounce } from './useDebounce';
|
||||
import { useInterval } from './useInterval';
|
||||
import { useDocumentTitle } from './useDocumentTitle';
|
||||
import { useDydxClient } from './useDydxClient';
|
||||
import { useGovernanceVariables } from './useGovernanceVariables';
|
||||
import { useAccountBalance } from './useAccountBalance';
|
||||
import { useAccounts } from './useAccounts';
|
||||
import { useAnalytics } from './useAnalytics';
|
||||
@@ -15,7 +14,6 @@ import { useInitializePage } from './useInitializePage';
|
||||
import { useIsFirstRender } from './useIsFirstRender';
|
||||
import { useLocaleSeparators } from './useLocaleSeparators';
|
||||
import { useLocalStorage } from './useLocalStorage';
|
||||
import { useNextClobPairId } from './useNextClobPairId';
|
||||
import { useNow } from './useNow';
|
||||
import { useOnClickOutside } from './useOnClickOutside';
|
||||
import { usePageTitlePriceUpdates } from './usePageTitlePriceUpdates';
|
||||
@@ -36,7 +34,6 @@ export {
|
||||
useDebounce,
|
||||
useDocumentTitle,
|
||||
useDydxClient,
|
||||
useGovernanceVariables,
|
||||
useAccountBalance,
|
||||
useAccounts,
|
||||
useAnalytics,
|
||||
@@ -45,7 +42,6 @@ export {
|
||||
useIsFirstRender,
|
||||
useLocaleSeparators,
|
||||
useLocalStorage,
|
||||
useNextClobPairId,
|
||||
useNow,
|
||||
useOnClickOutside,
|
||||
usePageTitlePriceUpdates,
|
||||
|
||||
@@ -11,7 +11,7 @@ import { useDydxClient, useLocalStorage } from '@/hooks';
|
||||
import { store } from '@/state/_store';
|
||||
|
||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||
import { getAppTheme, getAppColorMode } from '@/state/configsSelectors';
|
||||
import { getAppTheme } from '@/state/configsSelectors';
|
||||
import { getSelectedLocale } from '@/state/localizationSelectors';
|
||||
import { getCurrentMarketId, getMarketIds } from '@/state/perpetualsSelectors';
|
||||
|
||||
@@ -30,7 +30,6 @@ export const useTradingView = ({
|
||||
}) => {
|
||||
const marketId = useSelector(getCurrentMarketId);
|
||||
const appTheme = useSelector(getAppTheme);
|
||||
const appColorMode = useSelector(getAppColorMode);
|
||||
const marketIds = useSelector(getMarketIds, shallowEqual);
|
||||
const selectedLocale = useSelector(getSelectedLocale);
|
||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||
@@ -47,7 +46,7 @@ export const useTradingView = ({
|
||||
useEffect(() => {
|
||||
if (hasMarkets && isClientConnected && marketId) {
|
||||
const widgetOptions = getWidgetOptions();
|
||||
const widgetOverrides = getWidgetOverrides({ appTheme, appColorMode });
|
||||
const widgetOverrides = getWidgetOverrides(appTheme);
|
||||
const options = {
|
||||
// debug: true,
|
||||
...widgetOptions,
|
||||
@@ -76,14 +75,7 @@ export const useTradingView = ({
|
||||
tvWidgetRef.current = null;
|
||||
setIsChartReady(false);
|
||||
};
|
||||
}, [
|
||||
getCandlesForDatafeed,
|
||||
isClientConnected,
|
||||
hasMarkets,
|
||||
selectedLocale,
|
||||
selectedNetwork,
|
||||
!!marketId,
|
||||
]);
|
||||
}, [getCandlesForDatafeed, isClientConnected, hasMarkets, selectedLocale, selectedNetwork, !!marketId]);
|
||||
|
||||
return { savedResolution };
|
||||
};
|
||||
|
||||
@@ -3,8 +3,8 @@ import { useSelector } from 'react-redux';
|
||||
|
||||
import type { IChartingLibraryWidget, ThemeName } from 'public/tradingview/charting_library';
|
||||
|
||||
import { AppColorMode, AppTheme } from '@/state/configs';
|
||||
import { getAppTheme, getAppColorMode } from '@/state/configsSelectors';
|
||||
import { AppTheme } from '@/state/configs';
|
||||
import { getAppTheme } from '@/state/configsSelectors';
|
||||
|
||||
import { getWidgetOverrides } from '@/lib/tradingView/utils';
|
||||
|
||||
@@ -29,7 +29,6 @@ export const useTradingViewTheme = ({
|
||||
isWidgetReady?: boolean;
|
||||
}) => {
|
||||
const appTheme: AppTheme = useSelector(getAppTheme);
|
||||
const appColorMode: AppColorMode = useSelector(getAppColorMode);
|
||||
|
||||
useEffect(() => {
|
||||
if (tvWidget && isWidgetReady) {
|
||||
@@ -56,24 +55,10 @@ export const useTradingViewTheme = ({
|
||||
}
|
||||
}
|
||||
|
||||
const { overrides, studies_overrides } = getWidgetOverrides({ appTheme, appColorMode });
|
||||
const { overrides, studies_overrides } = getWidgetOverrides(appTheme);
|
||||
tvWidget?.applyOverrides(overrides);
|
||||
tvWidget?.applyStudiesOverrides(studies_overrides);
|
||||
|
||||
// Necessary to update existing indicators
|
||||
const volumeStudyId = tvWidget
|
||||
?.activeChart()
|
||||
?.getAllStudies()
|
||||
?.find((x) => x.name === 'Volume')?.id;
|
||||
|
||||
if (volumeStudyId) {
|
||||
const volume = tvWidget?.activeChart()?.getStudyById(volumeStudyId);
|
||||
volume.applyOverrides({
|
||||
'volume.color.0': studies_overrides['volume.volume.color.0'],
|
||||
'volume.color.1': studies_overrides['volume.volume.color.1'],
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [appTheme, appColorMode]);
|
||||
}, [appTheme]);
|
||||
};
|
||||
|
||||
@@ -6,22 +6,14 @@ import { NOBLE_BECH32_PREFIX, LocalWallet, type Subaccount } from '@dydxprotocol
|
||||
|
||||
import { OnboardingGuard, OnboardingState, type EvmDerivedAddresses } from '@/constants/account';
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { LocalStorageKey, LOCAL_STORAGE_VERSIONS } from '@/constants/localStorage';
|
||||
import {
|
||||
DydxAddress,
|
||||
EvmAddress,
|
||||
PrivateInformation,
|
||||
TEST_WALLET_EVM_ADDRESS,
|
||||
WalletType,
|
||||
} from '@/constants/wallets';
|
||||
import { DydxAddress, EvmAddress, PrivateInformation } from '@/constants/wallets';
|
||||
|
||||
import { setOnboardingState, setOnboardingGuard } from '@/state/account';
|
||||
import { forceOpenDialog } from '@/state/dialogs';
|
||||
|
||||
import abacusStateManager from '@/lib/abacus';
|
||||
import { log } from '@/lib/telemetry';
|
||||
import { testFlags } from '@/lib/testFlags';
|
||||
|
||||
import { useDydxClient } from './useDydxClient';
|
||||
import { useLocalStorage } from './useLocalStorage';
|
||||
@@ -161,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]);
|
||||
@@ -171,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,
|
||||
@@ -192,26 +178,7 @@ const useAccountsContext = () => {
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (walletType === WalletType.TestWallet) {
|
||||
// Get override values. Use the testFlags value if it exists, otherwise use the previously
|
||||
// saved value where possible. If neither exist, use a default garbage value.
|
||||
const addressOverride: DydxAddress = testFlags.addressOverride as DydxAddress ||
|
||||
evmDerivedAddresses?.[TEST_WALLET_EVM_ADDRESS]?.dydxAddress as DydxAddress ||
|
||||
'dydx1';
|
||||
|
||||
dispatch(setOnboardingState(OnboardingState.WalletConnected));
|
||||
|
||||
// Set variables.
|
||||
saveEvmDerivedAccount({
|
||||
evmAddress: TEST_WALLET_EVM_ADDRESS,
|
||||
dydxAddress: addressOverride,
|
||||
});
|
||||
const wallet = new LocalWallet();
|
||||
wallet.address = addressOverride;
|
||||
setLocalDydxWallet(wallet);
|
||||
|
||||
dispatch(setOnboardingState(OnboardingState.AccountConnected));
|
||||
} else if (connectedDydxAddress && signerGraz) {
|
||||
if (connectedDydxAddress && signerGraz) {
|
||||
dispatch(setOnboardingState(OnboardingState.WalletConnected));
|
||||
try {
|
||||
setLocalDydxWallet(await LocalWallet.fromOfflineSigner(signerGraz));
|
||||
@@ -257,7 +224,6 @@ const useAccountsContext = () => {
|
||||
if (hdKey?.mnemonic) {
|
||||
const nobleWallet = await LocalWallet.fromMnemonic(hdKey.mnemonic, NOBLE_BECH32_PREFIX);
|
||||
abacusStateManager.setNobleWallet(nobleWallet);
|
||||
setLocalNobleWallet(nobleWallet);
|
||||
}
|
||||
};
|
||||
setNobleWallet();
|
||||
@@ -356,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];
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
|
||||
import { AppTheme, AppThemeSetting, AppColorMode, AppThemeSystemSetting } from '@/state/configs';
|
||||
import { getAppThemeSetting, getAppColorMode } from '@/state/configsSelectors';
|
||||
|
||||
import { Themes } from '@/styles/themes';
|
||||
|
||||
export const AppThemeAndColorModeProvider = ({ ...props }) => {
|
||||
return <ThemeProvider theme={useAppThemeAndColorModeContext()} {...props} />;
|
||||
};
|
||||
|
||||
export const useAppThemeAndColorModeContext = () => {
|
||||
const themeSetting: AppThemeSetting = useSelector(getAppThemeSetting);
|
||||
const colorMode: AppColorMode = useSelector(getAppColorMode);
|
||||
|
||||
const darkModePref = globalThis.matchMedia('(prefers-color-scheme: dark)');
|
||||
|
||||
const [systemPreference, setSystemPreference] = useState(
|
||||
darkModePref.matches ? AppTheme.Dark : AppTheme.Light
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const handler = (e) => {
|
||||
if (e.matches) {
|
||||
setSystemPreference(AppTheme.Dark);
|
||||
} else {
|
||||
setSystemPreference(AppTheme.Light);
|
||||
}
|
||||
};
|
||||
darkModePref.addEventListener('change', handler);
|
||||
return () => darkModePref.removeEventListener('change', handler);
|
||||
}, []);
|
||||
|
||||
const getThemeFromSetting = (): AppTheme => {
|
||||
switch (themeSetting) {
|
||||
case AppThemeSystemSetting.System:
|
||||
return systemPreference;
|
||||
case AppTheme.Classic:
|
||||
case AppTheme.Dark:
|
||||
case AppTheme.Light:
|
||||
return themeSetting;
|
||||
}
|
||||
};
|
||||
|
||||
return Themes[getThemeFromSetting()][colorMode];
|
||||
};
|
||||
@@ -1,6 +1,5 @@
|
||||
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import {
|
||||
BECH32_PREFIX,
|
||||
CompositeClient,
|
||||
@@ -10,13 +9,11 @@ import {
|
||||
onboarding,
|
||||
Network,
|
||||
ValidatorConfig,
|
||||
type ProposalStatus,
|
||||
} from '@dydxprotocol/v4-client-js';
|
||||
|
||||
import type { ResolutionString } from 'public/tradingview/charting_library';
|
||||
|
||||
import type { ConnectNetworkEvent, NetworkConfig } from '@/constants/abacus';
|
||||
import { DEFAULT_TRANSACTION_MEMO } from '@/constants/analytics';
|
||||
import { type Candle, RESOLUTION_MAP } from '@/constants/candles';
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
import { DydxChainAsset } from '@/constants/wallets';
|
||||
@@ -71,22 +68,17 @@ const useDydxClientContext = () => {
|
||||
new Network(
|
||||
selectedNetwork,
|
||||
new IndexerConfig(networkConfig.indexerUrl, networkConfig.websocketUrl),
|
||||
new ValidatorConfig(
|
||||
networkConfig.validatorUrl,
|
||||
networkConfig.chainId,
|
||||
new ValidatorConfig(networkConfig.validatorUrl, networkConfig.chainId,
|
||||
{
|
||||
USDC_DENOM: tokensConfigs[DydxChainAsset.USDC].denom,
|
||||
USDC_DECIMALS: tokensConfigs[DydxChainAsset.USDC].decimals,
|
||||
USDC_GAS_DENOM: tokensConfigs[DydxChainAsset.USDC].gasDenom,
|
||||
CHAINTOKEN_DENOM: tokensConfigs[DydxChainAsset.CHAINTOKEN].denom,
|
||||
CHAINTOKEN_DECIMALS: tokensConfigs[DydxChainAsset.CHAINTOKEN].decimals,
|
||||
},
|
||||
{
|
||||
broadcastPollIntervalMs: 3_000,
|
||||
broadcastTimeoutMs: 60_000,
|
||||
},
|
||||
DEFAULT_TRANSACTION_MEMO
|
||||
)
|
||||
}, {
|
||||
broadcastPollIntervalMs: 3_000,
|
||||
broadcastTimeoutMs: 60_000,
|
||||
})
|
||||
)
|
||||
);
|
||||
setCompositeClient(initializedClient);
|
||||
@@ -119,36 +111,6 @@ const useDydxClientContext = () => {
|
||||
};
|
||||
|
||||
// ------ Public Methods ------ //
|
||||
const requestAllPerpetualMarkets = useCallback(async () => {
|
||||
try {
|
||||
const { markets } =
|
||||
(await compositeClient?.indexerClient.markets.getPerpetualMarkets()) || {};
|
||||
return markets || [];
|
||||
} catch (error) {
|
||||
log('useDydxClient/getPerpetualMarkets', error);
|
||||
return [];
|
||||
}
|
||||
}, [compositeClient]);
|
||||
|
||||
/**
|
||||
* @param proposalStatus - Optional filter for proposal status. If not provided, all proposals in ProposalStatus.VotingPeriod will be returned.
|
||||
*/
|
||||
const requestAllGovernanceProposals = useCallback(
|
||||
async (proposalStatus?: ProposalStatus) => {
|
||||
try {
|
||||
const allGovProposals = await compositeClient?.validatorClient.get.getAllGovProposals(
|
||||
proposalStatus
|
||||
);
|
||||
|
||||
return allGovProposals;
|
||||
} catch (error) {
|
||||
log('useDydxClient/getProposals', error);
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
[compositeClient]
|
||||
);
|
||||
|
||||
const requestCandles = useCallback(
|
||||
async ({
|
||||
marketId,
|
||||
@@ -263,8 +225,6 @@ const useDydxClientContext = () => {
|
||||
getWalletFromEvmSignature,
|
||||
|
||||
// Public Methods
|
||||
requestAllPerpetualMarkets,
|
||||
requestAllGovernanceProposals,
|
||||
getCandlesForDatafeed,
|
||||
screenAddresses,
|
||||
};
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
import { useSelectedNetwork } from '@/hooks';
|
||||
|
||||
export interface GovernanceVariables {
|
||||
newMarketProposal: {
|
||||
initialDepositAmount: number;
|
||||
delayBlocks: number;
|
||||
newMarketsMethodology: string;
|
||||
};
|
||||
}
|
||||
|
||||
export const useGovernanceVariables = (): GovernanceVariables => {
|
||||
const { selectedNetwork } = useSelectedNetwork();
|
||||
const governanceVars = ENVIRONMENT_CONFIG_MAP[selectedNetwork].governance as GovernanceVariables;
|
||||
return governanceVars;
|
||||
};
|
||||
@@ -33,7 +33,7 @@ export const useMarketsData = (
|
||||
return Object.values(allPerpetualMarkets)
|
||||
.filter(isTruthy)
|
||||
.map((marketData) => ({
|
||||
asset: allAssets[marketData.assetId] ?? {},
|
||||
asset: allAssets[marketData.assetId],
|
||||
tickSizeDecimals: marketData.configs?.tickSizeDecimals,
|
||||
...marketData,
|
||||
...marketData.perpetual,
|
||||
@@ -46,10 +46,9 @@ export const useMarketsData = (
|
||||
|
||||
if (searchFilter) {
|
||||
return filtered.filter(
|
||||
({ asset, id }) =>
|
||||
({ asset }) =>
|
||||
asset?.name?.toLocaleLowerCase().includes(searchFilter.toLowerCase()) ||
|
||||
asset?.id?.toLocaleLowerCase().includes(searchFilter.toLowerCase()) ||
|
||||
id?.toLocaleLowerCase().includes(searchFilter.toLowerCase())
|
||||
asset?.id?.toLocaleLowerCase().includes(searchFilter.toLowerCase())
|
||||
);
|
||||
}
|
||||
return filtered;
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useQuery } from 'react-query';
|
||||
|
||||
import {
|
||||
MsgCreateClobPair,
|
||||
MsgCreateOracleMarket,
|
||||
MsgCreatePerpetual,
|
||||
MsgDelayMessage,
|
||||
MsgUpdateClobPair,
|
||||
TYPE_URL_MSG_CREATE_CLOB_PAIR,
|
||||
TYPE_URL_MSG_CREATE_ORACLE_MARKET,
|
||||
TYPE_URL_MSG_CREATE_PERPETUAL,
|
||||
TYPE_URL_MSG_DELAY_MESSAGE,
|
||||
TYPE_URL_MSG_UPDATE_CLOB_PAIR,
|
||||
} from '@dydxprotocol/v4-client-js';
|
||||
|
||||
import type { PerpetualMarketResponse } from '@/constants/indexer';
|
||||
import { useDydxClient } from '@/hooks/useDydxClient';
|
||||
|
||||
export const useNextClobPairId = () => {
|
||||
const { isConnected, requestAllPerpetualMarkets, requestAllGovernanceProposals } =
|
||||
useDydxClient();
|
||||
|
||||
const { data: perpetualMarkets, status: perpetualMarketsStatus } = useQuery({
|
||||
enabled: isConnected,
|
||||
queryKey: 'requestAllPerpetualMarkets',
|
||||
queryFn: requestAllPerpetualMarkets,
|
||||
refetchInterval: 60_000,
|
||||
staleTime: 60_000,
|
||||
});
|
||||
|
||||
const { data: allGovProposals, status: allGovProposalsStatus } = useQuery({
|
||||
enabled: isConnected,
|
||||
queryKey: 'requestAllActiveGovernanceProposals',
|
||||
queryFn: () => requestAllGovernanceProposals(),
|
||||
refetchInterval: 10_000,
|
||||
staleTime: 10_000,
|
||||
});
|
||||
|
||||
/**
|
||||
*
|
||||
* @param message from proposal. Each message is wrapped in a type any (on purpose).
|
||||
* @param callback method used to compile all clobPairIds, perpetualIds, marketIds, etc.
|
||||
*/
|
||||
const decodeMsgForClobPairId = (message: any, callback: (id?: number) => void): any => {
|
||||
const { typeUrl, value } = message;
|
||||
|
||||
switch (typeUrl) {
|
||||
case TYPE_URL_MSG_CREATE_ORACLE_MARKET: {
|
||||
const decodedValue = MsgCreateOracleMarket.decode(value);
|
||||
callback(decodedValue.params?.id);
|
||||
break;
|
||||
}
|
||||
case TYPE_URL_MSG_CREATE_PERPETUAL: {
|
||||
const decodedValue = MsgCreatePerpetual.decode(value);
|
||||
callback(decodedValue.params?.id);
|
||||
callback(decodedValue.params?.marketId);
|
||||
break;
|
||||
}
|
||||
case TYPE_URL_MSG_CREATE_CLOB_PAIR: {
|
||||
const decodedValue = MsgCreateClobPair.decode(value);
|
||||
callback(decodedValue.clobPair?.id);
|
||||
callback(decodedValue.clobPair?.perpetualClobMetadata?.perpetualId);
|
||||
break;
|
||||
}
|
||||
case TYPE_URL_MSG_UPDATE_CLOB_PAIR: {
|
||||
const decodedValue = MsgUpdateClobPair.decode(value);
|
||||
callback(decodedValue.clobPair?.id);
|
||||
callback(decodedValue.clobPair?.perpetualClobMetadata?.perpetualId);
|
||||
break;
|
||||
}
|
||||
case TYPE_URL_MSG_DELAY_MESSAGE: {
|
||||
const decodedValue = MsgDelayMessage.decode(value);
|
||||
decodeMsgForClobPairId(decodedValue.msg, callback);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const nextAvailableClobPairId = useMemo(() => {
|
||||
const idsFromProposals: number[] = [];
|
||||
|
||||
if (allGovProposals && Object.values(allGovProposals.proposals).length > 0) {
|
||||
const proposals = allGovProposals.proposals;
|
||||
proposals.forEach((proposal) => {
|
||||
if (proposal.messages) {
|
||||
proposal.messages.map((message) => {
|
||||
decodeMsgForClobPairId(message, (id?: number) => {
|
||||
if (id) {
|
||||
idsFromProposals.push(id);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (perpetualMarkets && Object.values(perpetualMarkets).length > 0) {
|
||||
const clobPairIds = Object.values(perpetualMarkets)?.map((perpetualMarket) =>
|
||||
Number((perpetualMarket as PerpetualMarketResponse).clobPairId)
|
||||
);
|
||||
|
||||
const nextAvailableClobPairId = Math.max(...[...clobPairIds, ...idsFromProposals]) + 1;
|
||||
return nextAvailableClobPairId;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}, [perpetualMarkets, allGovProposals]);
|
||||
|
||||
return {
|
||||
allGovProposalsStatus,
|
||||
perpetualMarketsStatus,
|
||||
nextAvailableClobPairId,
|
||||
};
|
||||
};
|
||||
@@ -1,118 +0,0 @@
|
||||
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import type { ExchangeConfigItem, PotentialMarketItem } from '@/constants/potentialMarkets';
|
||||
|
||||
import { log } from '@/lib/telemetry';
|
||||
|
||||
import { useStringGetter } from './useStringGetter';
|
||||
|
||||
const PotentialMarketsContext = createContext<ReturnType<typeof usePotentialMarketsContext>>({
|
||||
potentialMarkets: undefined,
|
||||
exchangeConfigs: undefined,
|
||||
hasPotentialMarketsData: false,
|
||||
liquidityTiers: {
|
||||
0: {
|
||||
label: 'Large-cap',
|
||||
initialMarginFraction: 0.05,
|
||||
maintenanceMarginFraction: 0.03,
|
||||
impactNotional: 10_000,
|
||||
},
|
||||
1: {
|
||||
label: 'Mid-cap',
|
||||
initialMarginFraction: 0.1,
|
||||
maintenanceMarginFraction: 0.05,
|
||||
impactNotional: 5_000,
|
||||
},
|
||||
2: {
|
||||
label: 'Long-tail',
|
||||
initialMarginFraction: 0.2,
|
||||
maintenanceMarginFraction: 0.1,
|
||||
impactNotional: 2_500,
|
||||
},
|
||||
3: {
|
||||
label: 'Safety',
|
||||
initialMarginFraction: 1,
|
||||
maintenanceMarginFraction: 0.2,
|
||||
impactNotional: 2_500,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
PotentialMarketsContext.displayName = 'PotentialMarkets';
|
||||
|
||||
export const PotentialMarketsProvider = ({ ...props }) => (
|
||||
<PotentialMarketsContext.Provider value={usePotentialMarketsContext()} {...props} />
|
||||
);
|
||||
|
||||
export const usePotentialMarkets = () => useContext(PotentialMarketsContext);
|
||||
|
||||
const EXCHANGE_CONFIG_FILE_PATH = '/configs/potentialMarketExchangeConfig.json';
|
||||
const POTENTIAL_MARKETS_FILE_PATH = '/configs/potentialMarketParameters.json';
|
||||
|
||||
export const usePotentialMarketsContext = () => {
|
||||
const stringGetter = useStringGetter();
|
||||
const [potentialMarkets, setPotentialMarkets] = useState<PotentialMarketItem[]>();
|
||||
const [exchangeConfigs, setExchangeConfigs] = useState<Record<string, ExchangeConfigItem[]>>();
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
fetch(POTENTIAL_MARKETS_FILE_PATH)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
setPotentialMarkets(data as PotentialMarketItem[]);
|
||||
});
|
||||
} catch (error) {
|
||||
log('usePotentialMarkets/potentialMarkets', error);
|
||||
setPotentialMarkets(undefined);
|
||||
}
|
||||
|
||||
try {
|
||||
fetch(EXCHANGE_CONFIG_FILE_PATH)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
setExchangeConfigs(data as Record<string, ExchangeConfigItem[]>);
|
||||
});
|
||||
} catch (error) {
|
||||
log('usePotentialMarkets/exchangeConfigs', error);
|
||||
setExchangeConfigs(undefined);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const liquidityTiers = useMemo(
|
||||
() => ({
|
||||
0: {
|
||||
label: stringGetter({ key: STRING_KEYS.LARGE_CAP }),
|
||||
initialMarginFraction: 0.05,
|
||||
maintenanceMarginFraction: 0.03,
|
||||
impactNotional: 10_000,
|
||||
},
|
||||
1: {
|
||||
label: stringGetter({ key: STRING_KEYS.MID_CAP }),
|
||||
initialMarginFraction: 0.1,
|
||||
maintenanceMarginFraction: 0.05,
|
||||
impactNotional: 5_000,
|
||||
},
|
||||
2: {
|
||||
label: stringGetter({ key: STRING_KEYS.LONG_TAIL }),
|
||||
initialMarginFraction: 0.2,
|
||||
maintenanceMarginFraction: 0.1,
|
||||
impactNotional: 2_500,
|
||||
},
|
||||
3: {
|
||||
label: stringGetter({ key: STRING_KEYS.SAFETY }),
|
||||
initialMarginFraction: 1,
|
||||
maintenanceMarginFraction: 0.2,
|
||||
impactNotional: 2_500,
|
||||
},
|
||||
}),
|
||||
[stringGetter]
|
||||
);
|
||||
|
||||
return {
|
||||
potentialMarkets,
|
||||
exchangeConfigs,
|
||||
hasPotentialMarketsData: Boolean(potentialMarkets && exchangeConfigs),
|
||||
liquidityTiers,
|
||||
};
|
||||
};
|
||||
@@ -2,16 +2,11 @@ import { createContext, useCallback, useContext, useEffect, useMemo, useState }
|
||||
import { shallowEqual, useSelector, useDispatch } from 'react-redux';
|
||||
import type { Nullable } from '@dydxprotocol/v4-abacus';
|
||||
import Long from 'long';
|
||||
import { type IndexedTx } from '@cosmjs/stargate';
|
||||
import type { IndexedTx } from '@cosmjs/stargate';
|
||||
import type { EncodeObject } from '@cosmjs/proto-signing';
|
||||
import { Method } from '@cosmjs/tendermint-rpc';
|
||||
|
||||
import {
|
||||
type LocalWallet,
|
||||
SubaccountClient,
|
||||
type GovAddNewMarketParams,
|
||||
utils,
|
||||
} from '@dydxprotocol/v4-client-js';
|
||||
import { type LocalWallet, SubaccountClient } from '@dydxprotocol/v4-client-js';
|
||||
|
||||
import type {
|
||||
AccountBalance,
|
||||
@@ -21,6 +16,7 @@ import type {
|
||||
} from '@/constants/abacus';
|
||||
|
||||
import { AMOUNT_RESERVED_FOR_GAS_USDC } from '@/constants/account';
|
||||
import { AnalyticsEvent } from '@/constants/analytics';
|
||||
import { QUANTUM_MULTIPLIER } from '@/constants/numbers';
|
||||
import { DydxAddress } from '@/constants/wallets';
|
||||
|
||||
@@ -28,13 +24,14 @@ import { setSubaccount, setHistoricalPnl, removeUncommittedOrderClientId } from
|
||||
import { getBalances } from '@/state/accountSelectors';
|
||||
|
||||
import abacusStateManager from '@/lib/abacus';
|
||||
import { hashFromTx } from '@/lib/hashfromTx';
|
||||
import { track } from '@/lib/analytics';
|
||||
import { MustBigNumber } from '@/lib/numbers';
|
||||
import { log } from '@/lib/telemetry';
|
||||
|
||||
import { useAccounts } from './useAccounts';
|
||||
import { useTokenConfigs } from './useTokenConfigs';
|
||||
import { useDydxClient } from './useDydxClient';
|
||||
import { useGovernanceVariables } from './useGovernanceVariables';
|
||||
import { hashFromTx } from '@/lib/hashfromTx';
|
||||
|
||||
type SubaccountContextType = ReturnType<typeof useSubaccountContext>;
|
||||
const SubaccountContext = createContext<SubaccountContextType>({} as SubaccountContextType);
|
||||
@@ -204,8 +201,8 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
value: {
|
||||
...transaction.msg,
|
||||
timeoutTimestamp: transaction.msg.timeoutTimestamp
|
||||
? // Squid returns timeoutTimestamp as Long, but the signer expects BigInt
|
||||
BigInt(Long.fromValue(transaction.msg.timeoutTimestamp).toString())
|
||||
// Squid returns timeoutTimestamp as Long, but the signer expects BigInt
|
||||
? BigInt(Long.fromValue(transaction.msg.timeoutTimestamp).toString())
|
||||
: undefined,
|
||||
},
|
||||
};
|
||||
@@ -304,8 +301,9 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
|
||||
const sendSquidWithdraw = useCallback(
|
||||
async (amount: number, payload: string, isCctp?: boolean) => {
|
||||
|
||||
const cctpWithdraw = () => {
|
||||
return new Promise<string>((resolve, reject) =>
|
||||
return new Promise<string>((resolve, reject) =>
|
||||
abacusStateManager.cctpWithdraw((success, error, data) => {
|
||||
const parsedData = JSON.parse(data);
|
||||
if (success && parsedData?.code == 0) {
|
||||
@@ -314,8 +312,8 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
reject(error);
|
||||
}
|
||||
})
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
if (isCctp) {
|
||||
return await cctpWithdraw();
|
||||
}
|
||||
@@ -415,32 +413,6 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
[subaccountClient]
|
||||
);
|
||||
|
||||
const { newMarketProposal } = useGovernanceVariables();
|
||||
|
||||
// ------ Governance Methods ------ //
|
||||
const submitNewMarketProposal = useCallback(
|
||||
async (params: GovAddNewMarketParams) => {
|
||||
if (!compositeClient) {
|
||||
throw new Error('client not initialized');
|
||||
} else if (!localDydxWallet) {
|
||||
throw new Error('wallet not initialized');
|
||||
} else if (!newMarketProposal) {
|
||||
throw new Error('governance variables not initialized');
|
||||
}
|
||||
|
||||
const response = await compositeClient.submitGovAddNewMarketProposal(
|
||||
localDydxWallet,
|
||||
params,
|
||||
utils.getGovAddNewMarketTitle(params.ticker),
|
||||
utils.getGovAddNewMarketSummary(params.ticker, newMarketProposal.delayBlocks),
|
||||
BigInt(newMarketProposal.initialDepositAmount).toString()
|
||||
);
|
||||
|
||||
return response;
|
||||
},
|
||||
[compositeClient, localDydxWallet]
|
||||
);
|
||||
|
||||
return {
|
||||
// Deposit/Withdraw/Faucet Methods
|
||||
deposit,
|
||||
@@ -455,8 +427,5 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
placeOrder,
|
||||
closePosition,
|
||||
cancelOrder,
|
||||
|
||||
// Governance Methods
|
||||
submitNewMarketProposal,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5,25 +5,23 @@ import { useSelectedNetwork } from '@/hooks';
|
||||
const FALLBACK_URL = 'https://help.dydx.exchange/';
|
||||
|
||||
export interface LinksConfigs {
|
||||
tos: string;
|
||||
privacy: string;
|
||||
mintscan: string;
|
||||
mintscanBase: string;
|
||||
feedback?: string;
|
||||
help?: string;
|
||||
blogs?: string;
|
||||
foundation?: string;
|
||||
initialMarginFractionLearnMore?: string;
|
||||
reduceOnlyLearnMore?: string;
|
||||
documentation?: string;
|
||||
community?: string;
|
||||
governanceLearnMore?: string;
|
||||
newMarketProposalLearnMore: string;
|
||||
stakingLearnMore?: string;
|
||||
keplrDashboard?: string;
|
||||
strideZoneApp?: string;
|
||||
accountExportLearnMore?: string;
|
||||
walletLearnMore?: string;
|
||||
tos: string,
|
||||
privacy: string,
|
||||
mintscan: string,
|
||||
mintscanBase: string,
|
||||
feedback?: string,
|
||||
help?: string,
|
||||
blogs?: string,
|
||||
foundation?: string,
|
||||
initialMarginFractionLearnMore?: string,
|
||||
reduceOnlyLearnMore?: string,
|
||||
documentation?: string,
|
||||
community?: string,
|
||||
governanceLearnMore?: string,
|
||||
stakingLearnMore?: string,
|
||||
keplrDashboard?: string,
|
||||
accountExportLearnMore?: string,
|
||||
walletLearnMore?: string
|
||||
}
|
||||
|
||||
export const useURLConfigs = (): LinksConfigs => {
|
||||
@@ -44,10 +42,8 @@ export const useURLConfigs = (): LinksConfigs => {
|
||||
documentation: linksConfigs.documentation || FALLBACK_URL,
|
||||
community: linksConfigs.community || FALLBACK_URL,
|
||||
governanceLearnMore: linksConfigs.governanceLearnMore || FALLBACK_URL,
|
||||
newMarketProposalLearnMore: linksConfigs.newMarketProposalLearnMore || FALLBACK_URL,
|
||||
stakingLearnMore: linksConfigs.stakingLearnMore || FALLBACK_URL,
|
||||
keplrDashboard: linksConfigs.keplrDashboard || FALLBACK_URL,
|
||||
strideZoneApp: linksConfigs.strideZoneApp || FALLBACK_URL,
|
||||
accountExportLearnMore: linksConfigs.accountExportLearnMore || FALLBACK_URL,
|
||||
walletLearnMore: linksConfigs.walletLearnMore || FALLBACK_URL,
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@ import { useCallback, useEffect, useState, useMemo } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { EvmDerivedAddresses } from '@/constants/account';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { LocalStorageKey } from '@/constants/localStorage';
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
|
||||
@@ -39,7 +38,6 @@ import { getWalletConnection, parseWalletError } from '@/lib/wallet';
|
||||
import { log } from '@/lib/telemetry';
|
||||
|
||||
import { useStringGetter } from './useStringGetter';
|
||||
import { testFlags } from '@/lib/testFlags';
|
||||
|
||||
export const useWalletConnection = () => {
|
||||
const stringGetter = useStringGetter();
|
||||
@@ -115,15 +113,7 @@ export const useWalletConnection = () => {
|
||||
});
|
||||
|
||||
const connectWallet = useCallback(
|
||||
async ({
|
||||
walletType,
|
||||
forceConnect,
|
||||
isAccountConnected,
|
||||
}: {
|
||||
walletType?: WalletType;
|
||||
forceConnect?: boolean;
|
||||
isAccountConnected?: boolean;
|
||||
}) => {
|
||||
async ({ walletType, forceConnect }: { walletType?: WalletType; forceConnect?: boolean }) => {
|
||||
if (!walletType) return { walletType, walletConnectionType };
|
||||
|
||||
const walletConnection = getWalletConnection({ walletType });
|
||||
@@ -148,9 +138,10 @@ export const useWalletConnection = () => {
|
||||
walletType: cosmosWalletType,
|
||||
});
|
||||
}
|
||||
} else if (walletConnection.type === WalletConnectionType.TestWallet) {
|
||||
saveEvmAddress(STRING_KEYS.TEST_WALLET as EvmAddress);
|
||||
} else {
|
||||
const isAccountConnected = Boolean(
|
||||
evmAddress && evmDerivedAddresses[evmAddress]?.encryptedSignature
|
||||
);
|
||||
// if account connected (via remember me), do not show wagmi popup until forceConnect
|
||||
if (!isConnectedWagmi && (forceConnect || !isAccountConnected)) {
|
||||
await connectWagmi({
|
||||
@@ -163,20 +154,17 @@ export const useWalletConnection = () => {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
const { isErrorExpected } = parseWalletError({ error, stringGetter });
|
||||
if (!isErrorExpected) {
|
||||
throw Object.assign(
|
||||
new Error([error.message, error.cause?.message].filter(Boolean).join('\n')),
|
||||
{
|
||||
walletConnectionType: walletConnection?.type,
|
||||
}
|
||||
);
|
||||
}
|
||||
throw Object.assign(
|
||||
new Error([error.message, error.cause?.message].filter(Boolean).join('\n')),
|
||||
{
|
||||
walletConnectionType: walletConnection?.type,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
walletType,
|
||||
walletConnectionType: walletConnection?.type,
|
||||
walletConnectionType: walletConnection.type,
|
||||
};
|
||||
},
|
||||
[isConnectedGraz, signerGraz, isConnectedWagmi, signerWagmi]
|
||||
@@ -203,9 +191,6 @@ export const useWalletConnection = () => {
|
||||
try {
|
||||
const { walletType, walletConnectionType } = await connectWallet({
|
||||
walletType: selectedWalletType,
|
||||
isAccountConnected: Boolean(
|
||||
evmAddress && evmDerivedAddresses[evmAddress]?.encryptedSignature
|
||||
),
|
||||
});
|
||||
|
||||
setWalletType(walletType);
|
||||
@@ -228,7 +213,7 @@ export const useWalletConnection = () => {
|
||||
await disconnectWallet();
|
||||
}
|
||||
})();
|
||||
}, [selectedWalletType, signerWagmi, signerGraz, evmDerivedAddresses, evmAddress]);
|
||||
}, [selectedWalletType, signerWagmi, signerGraz]);
|
||||
|
||||
const selectWalletType = async (walletType: WalletType | undefined) => {
|
||||
if (selectedWalletType) {
|
||||
@@ -239,15 +224,6 @@ export const useWalletConnection = () => {
|
||||
setSelectedWalletType(walletType);
|
||||
};
|
||||
|
||||
// On page load, if testFlag.address is set, connect to the test wallet.
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (testFlags.addressOverride) {
|
||||
setSelectedWalletType(WalletType.TestWallet);
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
// Wallet connection
|
||||
walletType,
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { AppTheme } from '@/state/configs';
|
||||
import { getAppTheme } from '@/state/configsSelectors';
|
||||
|
||||
const ChaosLabsIcon: React.FC = () => {
|
||||
const appTheme = useSelector(getAppTheme);
|
||||
|
||||
const fills = appTheme === AppTheme.Light ? ['#1482E5', '#000000'] : ['#1482E5', '#E5E9EB'];
|
||||
|
||||
return (
|
||||
<svg width="91" height="17" viewBox="0 0 91 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M13.4384 13.2558C13.3846 13.2931 13.3295 13.3283 13.2724 13.3615L11.4238 14.4385L4.17188 10.2149V6.61884L11.4198 2.39746L13.2724 3.47652C13.3376 3.51449 13.4007 3.55521 13.4619 3.59848L8.28233 6.60962V6.60225L6.20661 7.81644V9.05132L8.28233 10.2629V9.0364L14.4967 5.41709C14.5028 5.48788 14.5055 5.55928 14.5055 5.63112V7.80972L10.3675 10.2318V11.4757L13.4384 13.2558Z"
|
||||
fill={fills[0]}
|
||||
/>
|
||||
<path
|
||||
d="M9.34397 1.18863L8.48587 0.688787C7.72318 0.244363 6.78308 0.244363 6.01972 0.688787L1.23307 3.47666C0.470044 3.92109 0 4.74241 0 5.63125V11.207C0 12.0958 0.470044 12.9172 1.23307 13.3616L6.01972 16.1495C6.78308 16.5939 7.72318 16.5939 8.48587 16.1495L9.348 15.6475L2.09628 11.4241V5.41158L2.09911 5.41323L2.09628 5.41L9.34397 1.18863Z"
|
||||
fill={fills[0]}
|
||||
/>
|
||||
<path d="M62.777 12.3629V4.57764H64.1102V11.1154H67.7133V12.3629H62.777Z" fill={fills[1]} />
|
||||
<path
|
||||
d="M70.2932 10.5919L69.5029 12.3629H68.0797L71.5585 4.57764H72.9817L76.4605 12.3629H75.0373L74.2464 10.5919H70.2932ZM73.7041 9.37795L72.2701 6.17032L70.8355 9.37795H73.7041Z"
|
||||
fill={fills[1]}
|
||||
/>
|
||||
<path
|
||||
d="M81.0141 12.3629H77.5581V4.57764H80.6304C81.1646 4.57764 81.6242 4.64075 82.0079 4.76698C82.3997 4.8932 82.6893 5.06398 82.8781 5.27931C83.2396 5.68026 83.4197 6.1332 83.4197 6.6381C83.4197 7.24693 83.2242 7.69991 82.8324 7.99692C82.6893 8.10087 82.5918 8.16767 82.5388 8.19737C82.4863 8.21968 82.3923 8.26047 82.2565 8.31987C82.7464 8.42382 83.1341 8.64289 83.4197 8.97699C83.7134 9.3037 83.8605 9.71213 83.8605 10.2021C83.8605 10.7442 83.6724 11.2231 83.2961 11.6389C82.8512 12.1215 82.0912 12.3629 81.0141 12.3629ZM78.8906 7.80756H80.5847C81.5489 7.80756 82.0307 7.48454 82.0307 6.83858C82.0307 6.46732 81.9138 6.20002 81.6806 6.03667C81.4468 5.87331 81.086 5.79164 80.5961 5.79164H78.8906V7.80756ZM78.8906 11.1489H80.9805C81.4697 11.1489 81.8426 11.0746 82.0986 10.9261C82.362 10.7701 82.4937 10.4806 82.4937 10.0574C82.4937 9.3668 81.9326 9.02154 80.8111 9.02154H78.8906V11.1489Z"
|
||||
fill={fills[1]}
|
||||
/>
|
||||
<path
|
||||
d="M87.9162 5.60121C87.5325 5.60121 87.216 5.67917 86.9674 5.8351C86.7194 5.99103 86.5951 6.22863 86.5951 6.54791C86.5951 6.85977 86.7194 7.1011 86.9674 7.27185C87.216 7.4352 87.7435 7.61341 88.5492 7.80647C89.3623 7.99953 89.9724 8.27053 90.379 8.61949C90.7929 8.96851 90.9999 9.48452 90.9999 10.1676C90.9999 10.8433 90.7405 11.3928 90.2204 11.816C89.701 12.2393 89.0196 12.4509 88.1763 12.4509C86.9412 12.4509 85.8459 12.0314 84.8896 11.1923L85.7249 10.201C86.5232 10.8842 87.3518 11.2257 88.2099 11.2257C88.6393 11.2257 88.9779 11.1366 89.2266 10.9584C89.4826 10.7728 89.6109 10.5314 89.6109 10.2345C89.6109 9.93003 89.49 9.69619 89.2494 9.53283C89.0156 9.36202 88.609 9.20981 88.0291 9.07616C87.4499 8.93511 87.0091 8.80885 86.708 8.6975C86.407 8.5787 86.1395 8.42643 85.9057 8.24083C85.4393 7.89188 85.2055 7.35726 85.2055 6.63702C85.2055 5.91678 85.4689 5.36361 85.9964 4.9775C86.5306 4.58397 87.1898 4.38721 87.9727 4.38721C88.4773 4.38721 88.9779 4.46889 89.4752 4.63224C89.9724 4.79558 90.4012 5.02577 90.7627 5.32277L90.0511 6.31402C89.8179 6.10612 89.5014 5.93534 89.1022 5.80169C88.7031 5.66804 88.308 5.60121 87.9162 5.60121Z"
|
||||
fill={fills[1]}
|
||||
/>
|
||||
<path
|
||||
d="M24.047 4.38721C22.8629 4.38721 21.861 4.77008 21.0648 5.54419L21.0634 5.54519C20.2745 6.31948 19.8807 7.2916 19.8807 8.43967C19.8807 9.58585 20.2665 10.5517 21.0433 11.3136L21.0439 11.3146C21.8268 12.0745 22.8072 12.4509 23.9643 12.4509C25.1463 12.4509 26.1536 11.9892 26.9707 11.0839L27.1609 10.8729L25.9722 9.65318L25.7558 9.85645C25.442 10.1501 25.1524 10.3555 24.8869 10.4827C24.6336 10.5973 24.3191 10.6603 23.9334 10.6603C23.3434 10.6603 22.8361 10.4504 22.3966 10.0177C21.9686 9.58323 21.7542 9.05029 21.7542 8.39841C21.7542 7.73954 21.9719 7.22084 22.4006 6.81607L22.402 6.81454C22.8367 6.39839 23.371 6.18802 24.0261 6.18802C24.4071 6.18802 24.7216 6.24839 24.9776 6.35892L24.9797 6.35987C25.2437 6.47129 25.5394 6.67559 25.866 6.98947L26.0904 7.20438L27.2583 5.92696L27.0729 5.72256C26.2665 4.83489 25.2511 4.38721 24.047 4.38721Z"
|
||||
fill={fills[1]}
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M47.6624 4.38721C46.5167 4.38721 45.5396 4.77222 44.7521 5.54468C43.9625 6.31199 43.5687 7.27749 43.5687 8.41904C43.5687 9.55454 43.9632 10.5194 44.7514 11.2929L44.7527 11.2939C45.5403 12.0594 46.5173 12.4406 47.6624 12.4406C48.8074 12.4406 49.7845 12.0594 50.572 11.2939L50.5734 11.2929C51.3616 10.5194 51.756 9.55454 51.756 8.41904C51.756 7.27749 51.3623 6.312 50.5727 5.54469C49.7851 4.77223 48.8081 4.38721 47.6624 4.38721ZM45.4207 8.41904C45.4207 7.76676 45.6364 7.22501 46.0671 6.77549C46.5039 6.32689 47.0294 6.10561 47.6624 6.10561C48.2954 6.10561 48.8168 6.32697 49.2462 6.77466L49.2476 6.77617C49.6857 7.22615 49.9034 7.7677 49.9034 8.41904C49.9034 9.06265 49.6864 9.60104 49.2476 10.0516L49.2462 10.0531C48.8168 10.5008 48.2954 10.7222 47.6624 10.7222C47.0294 10.7222 46.5039 10.5009 46.0671 10.0523C45.6357 9.60218 45.4207 9.06359 45.4207 8.41904Z"
|
||||
fill={fills[1]}
|
||||
/>
|
||||
<path
|
||||
d="M55.2113 4.38721C54.4439 4.38721 53.7767 4.58367 53.2277 4.99291C52.6605 5.41417 52.3843 6.02137 52.3843 6.77092C52.3843 7.50415 52.6222 8.09878 53.1396 8.49282C53.3768 8.68366 53.6463 8.83835 53.9446 8.95789L53.9514 8.96024C54.2423 9.06951 54.6576 9.18959 55.1898 9.32096L55.1938 9.32176C55.7153 9.4438 56.0345 9.57362 56.1944 9.69243L56.1991 9.69565L56.2038 9.69874C56.3355 9.78966 56.402 9.90967 56.402 10.098C56.402 10.2701 56.3362 10.4048 56.1756 10.523C56.0177 10.6376 55.7791 10.7119 55.4277 10.7119C54.7335 10.7119 54.0461 10.4338 53.36 9.83838L53.1262 9.63551L51.9791 11.0155L52.1975 11.2103C53.1228 12.0336 54.1933 12.4509 55.3968 12.4509C56.2179 12.4509 56.9134 12.2409 57.4537 11.7944C57.9987 11.3443 58.2748 10.7498 58.2748 10.0363C58.2748 9.34239 58.0652 8.77028 57.6029 8.37509C57.1809 8.00799 56.5721 7.74216 55.808 7.55804C55.4458 7.47001 55.1515 7.38669 54.923 7.3084C54.6926 7.22931 54.5461 7.16104 54.4648 7.10769C54.3257 7.00954 54.2571 6.88184 54.2571 6.68852C54.2571 6.48456 54.3277 6.36719 54.4574 6.28486C54.6227 6.17969 54.8498 6.11592 55.1596 6.11592C55.4814 6.11592 55.8087 6.17147 56.144 6.28523C56.4813 6.39984 56.73 6.54009 56.9033 6.69703L57.1567 6.92574L58.1646 5.50194L57.9496 5.32269C57.5874 5.02123 57.1621 4.79104 56.6769 4.62937C56.1937 4.46839 55.7052 4.38721 55.2113 4.38721Z"
|
||||
fill={fills[1]}
|
||||
/>
|
||||
<path
|
||||
d="M29.7507 4.56055H27.9297V12.3667H29.7507V9.42066H32.7195V12.3667H34.5406V4.56055H32.7195V7.68166H29.7507V4.56055Z"
|
||||
fill={fills[1]}
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M40.3586 4.56055H38.6659L35.2261 12.3667H37.1862L37.9072 10.7289H41.1173L41.8383 12.3667H43.7984L40.3586 4.56055ZM38.6686 9.00014L39.5126 7.08737L40.3559 9.00014H38.6686Z"
|
||||
fill={fills[1]}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChaosLabsIcon;
|
||||