Compare commits

..
Author SHA1 Message Date
Bill He 5b71710cef remove cexdeposit testflag 2024-01-30 11:07:37 -08:00
113 changed files with 549 additions and 50044 deletions
+32 -36
View File
@@ -9,15 +9,9 @@ import { GlobalStyle } from '@/styles/globalStyle';
import { SelectMenu, SelectItem } from '@/components/SelectMenu';
import { AppThemeAndColorModeProvider } from '@/hooks/useAppThemeAndColorMode';
import { AppThemeProvider } from '@/hooks/useAppTheme';
import {
AppTheme,
AppThemeSystemSetting,
AppColorMode,
setAppThemeSetting,
setAppColorMode,
} from '@/state/configs';
import { AppTheme, setAppTheme } from '@/state/configs';
import { setLocaleLoaded } from '@/state/localization';
import '@/index.css';
@@ -25,12 +19,26 @@ import './ladle.css';
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(setLocaleLoaded(true));
@@ -40,16 +48,15 @@ export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children
<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',
@@ -59,31 +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 />
<AppThemeAndColorModeProvider>
<AppThemeProvider>
<GlobalStyle />
<StoryContent>{children}</StoryContent>
</AppThemeAndColorModeProvider>
</Provider>
</AppThemeProvider>
</Provider>
);
};
+4 -5
View File
@@ -39,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.1",
"@dydxprotocol/v4-client-js": "^1.0.20",
"@dydxprotocol/v4-localization": "^1.1.22",
"@dydxprotocol/v4-abacus": "^1.3.2",
"@dydxprotocol/v4-client-js": "^1.0.17",
"@dydxprotocol/v4-localization": "^1.1.17",
"@ethersproject/providers": "^5.7.2",
"@js-joda/core": "^5.5.3",
"@radix-ui/react-accordion": "^1.1.2",
@@ -92,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",
@@ -162,4 +161,4 @@
"follow-redirects": "1.15.3"
}
}
}
}
+19 -22
View File
@@ -1,9 +1,5 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
overrides:
follow-redirects: 1.15.3
@@ -30,14 +26,14 @@ dependencies:
specifier: ^0.32.1
version: 0.32.2
'@dydxprotocol/v4-abacus':
specifier: ^1.4.1
version: 1.4.1
specifier: ^1.3.2
version: 1.3.2
'@dydxprotocol/v4-client-js':
specifier: ^1.0.20
version: 1.0.20
specifier: ^1.0.17
version: 1.0.17
'@dydxprotocol/v4-localization':
specifier: ^1.1.22
version: 1.1.22
specifier: ^1.1.17
version: 1.1.17
'@ethersproject/providers':
specifier: ^5.7.2
version: 5.7.2
@@ -188,9 +184,6 @@ dependencies:
color:
specifier: ^4.2.3
version: 4.2.3
cosmjs-types:
specifier: ^0.9.0
version: 0.9.0
crypto-js:
specifier: ^4.1.1
version: 4.1.1
@@ -1092,12 +1085,12 @@ packages:
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
dev: true
/@dydxprotocol/v4-abacus@1.4.1:
resolution: {integrity: sha512-u7OSQ2zPt0EqNlm0mE9L4gj4Xwbd7RDG/4fOyzrOZZsRgXedghXGBNxonbqgx6Rp7yRYfA4Il76y+k7EOZcU2Q==}
/@dydxprotocol/v4-abacus@1.3.2:
resolution: {integrity: sha512-zo0IHjGMlJRKOYDgNqNFQ9GtBJKJP4+Y9YY7V0X3Wt61ppKAYzodaYQhc9V/RYchcZTtS/xkicLug444YrvehQ==}
dev: false
/@dydxprotocol/v4-client-js@1.0.20:
resolution: {integrity: sha512-dXKW2NC1XlVVIRKvHWVDofLZSCPTJAaRY5eXzxH5CcXpnl2kdXorr7ykqWZxW0jHFPWWvRSJtUDqZN1qFrEe/w==}
/@dydxprotocol/v4-client-js@1.0.17:
resolution: {integrity: sha512-PbTKbzcS7VapuFRofkirUxkF9ThNS2tWYyr0asFOMUfebsQWMvTC1sYC/s1NZIiBeq3cFz9vKdZFbfsKi7Z1bw==}
dependencies:
'@cosmjs/amino': 0.32.2
'@cosmjs/encoding': 0.32.2
@@ -1106,7 +1099,7 @@ packages:
'@cosmjs/stargate': 0.32.2
'@cosmjs/tendermint-rpc': 0.32.2
'@cosmjs/utils': 0.32.2
'@dydxprotocol/v4-proto': 4.0.0-dev.0
'@dydxprotocol/v4-proto': 3.0.0-dev.0
'@osmonauts/lcd': 0.6.0
'@scure/bip32': 1.3.2
'@scure/bip39': 1.2.1
@@ -1125,12 +1118,12 @@ packages:
- utf-8-validate
dev: false
/@dydxprotocol/v4-localization@1.1.22:
resolution: {integrity: sha512-DURyvBx0qjXmtebSRMW4ZdTsX5xI8Mb6c7LQ8WUPU0O3Jr7n7iUT/phzZszTpwNOMFFMukMFtn7fHCgijw1TOg==}
/@dydxprotocol/v4-localization@1.1.17:
resolution: {integrity: sha512-kal1LrcihLMEv5YxaA/hd6Zl10Mp3x6jicoXDcXvtyNdrczAl3YapyI2nmeifRAPvfueOaY3W/sKkm2BiSKSsA==}
dev: false
/@dydxprotocol/v4-proto@4.0.0-dev.0:
resolution: {integrity: sha512-PC/xq5YJIisAd3jjIULJGrnujbrYkr5h4ehepnLc6U34nJT720iumKVMiPaezwRC+kHKTI1culpKNnlMnbeYBA==}
/@dydxprotocol/v4-proto@3.0.0-dev.0:
resolution: {integrity: sha512-hT6F/AgaTqv8Bwo7twpIhmjXvJE/Fx+3mmHHTuIXMeL6OhVtlOpcEQyHvBEAdh1VrNq/S7qWvdQD0fvC/UgKyA==}
dependencies:
protobufjs: 6.11.4
dev: false
@@ -14916,3 +14909,7 @@ packages:
/zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
dev: true
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

-19
View File
@@ -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

-20
View File
@@ -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

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 2.2 MiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 2.1 MiB

+13 -112
View File
@@ -11,13 +11,6 @@
],
"default": "dydxprotocol-mainnet"
},
"TESTFLIGHT": {
"environments": [
"dydxprotocol-mainnet",
"dydxprotocol-testnet"
],
"default": "dydxprotocol-mainnet"
},
"TESTNET": {
"environments": [
"dydxprotocol-testnet"
@@ -88,6 +81,7 @@
"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/",
@@ -115,13 +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"
}
}
},
"dydxprotocol-dev-2": {
@@ -167,6 +154,7 @@
"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/",
@@ -194,13 +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"
}
}
},
"dydxprotocol-dev-4": {
@@ -247,6 +228,7 @@
"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/",
@@ -274,13 +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"
}
}
},
"dydxprotocol-dev-5": {
@@ -326,6 +301,7 @@
"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/",
@@ -353,13 +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"
}
}
},
"dydxprotocol-staging": {
@@ -409,6 +378,7 @@
"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",
@@ -434,13 +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"
}
}
},
"dydxprotocol-staging-forced-update": {
@@ -514,13 +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"
}
}
},
"dydxprotocol-staging-west": {
@@ -570,6 +526,7 @@
"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",
@@ -595,13 +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"
}
}
},
"dydxprotocol-testnet": {
@@ -655,6 +605,7 @@
"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",
@@ -680,13 +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"
}
}
},
"dydxprotocol-testnet-dydx": {
@@ -737,6 +681,7 @@
"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",
@@ -762,13 +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"
}
}
},
"dydxprotocol-testnet-nodefleet": {
@@ -819,6 +757,7 @@
"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",
@@ -844,13 +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"
}
}
},
"dydxprotocol-testnet-kingnodes": {
@@ -901,6 +833,7 @@
"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",
@@ -926,13 +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"
}
}
},
"dydxprotocol-testnet-liquify": {
@@ -983,6 +909,7 @@
"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",
@@ -1008,13 +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"
}
}
},
"dydxprotocol-testnet-polkachu": {
@@ -1082,13 +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"
}
}
},
"dydxprotocol-testnet-bware": {
@@ -1139,6 +1052,7 @@
"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",
@@ -1164,13 +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"
}
}
},
"dydxprotocol-mainnet": {
@@ -1219,6 +1126,7 @@
"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]",
@@ -1246,13 +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]"
}
}
}
}
-7
View File
@@ -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": [],
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.6 KiB

+4 -10
View File
@@ -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,7 +44,6 @@ 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'));
@@ -83,10 +81,7 @@ 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={AppRoute.Markets} element={<MarketsPage />} />
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
{isTablet && (
<>
@@ -141,8 +136,7 @@ const providers = [
wrapProvider(LocalNotificationsProvider),
wrapProvider(NotificationsProvider),
wrapProvider(DialogAreaProvider),
wrapProvider(PotentialMarketsProvider),
wrapProvider(AppThemeAndColorModeProvider),
wrapProvider(AppThemeProvider),
];
const App = () => {
+1 -1
View File
@@ -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);
}
}
-1
View File
@@ -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',
+2 -2
View File
@@ -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;
+6 -10
View File
@@ -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-success);
--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-error);
--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-error);
--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));
`,
};
+12 -22
View File
@@ -24,25 +24,15 @@ export const Checkbox: React.FC<CheckboxProps> = ({
onCheckedChange,
id,
label,
disabled,
disabled
}) => (
<Styled.Container>
<Styled.Root
className={className}
checked={checked}
disabled={disabled}
onCheckedChange={onCheckedChange}
id={id}
>
<Styled.Root className={className} checked={checked} disabled={disabled} onCheckedChange={onCheckedChange} id={id}>
<Styled.Indicator>
<CheckIcon />
</Styled.Indicator>
</Styled.Root>
{label && (
<Styled.Label disabled={disabled} htmlFor={id}>
{label}
</Styled.Label>
)}
{label && <Styled.label disabled={disabled} htmlFor={id}>{label}</Styled.label>}
</Styled.Container>
);
@@ -52,6 +42,10 @@ Styled.Container = styled.div`
${layoutMixins.row}
gap: 1ch;
font: var(--font-small-book);
label {
cursor: pointer;
}
`;
Styled.Root = styled(Root)`
@@ -80,17 +74,13 @@ Styled.Indicator = styled(Indicator)`
align-items: center;
justify-content: center;
color: var(--color-text-button);
color: var(--color-text-2);
`;
Styled.Label = styled.label<{ disabled?: boolean }>`
cursor: pointer;
Styled.label = styled.div<{ disabled: boolean; }>`
color: var(--color-text-2);
${({ disabled }) =>
disabled &&
css`
cursor: not-allowed;
color: var(--color-text-0);
`}
${({disabled}) => disabled && css`
color: var(--color-text-0);
`}
`;
+4 -5
View File
@@ -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}
>
+3 -3
View File
@@ -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);
}
`}
`;
+1 -1
View File
@@ -62,6 +62,6 @@ Styled.DiffArrowContainer = styled.span<DiffArrowProps>`
`,
down: css`
transform: rotate(90deg);
`,
`
}[direction || 'right'])}
`;
+1 -1
View File
@@ -75,7 +75,7 @@ Styled.DiffValue = styled.div<{ hasInvalidNewValue?: boolean }>`
${({ hasInvalidNewValue }) =>
hasInvalidNewValue &&
css`
color: var(--color-error);
color: var(--color-negative);
`}
`;
+3 -3
View File
@@ -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);
}
`;
+7 -12
View File
@@ -6,34 +6,29 @@ import { StoryWrapper } from '.ladle/components';
export const DropdownMenuStory: Story<Parameters<typeof DropdownMenu>> = (args) => {
const exampleItems = [
{
value: '0',
label: 'Item 0',
onSelect: () => alert('Item 0 action'),
},
{
value: '1',
label: 'Item 1 (accent)',
label: 'Item 1',
onSelect: () => alert('Item 1 action'),
highlightColor: 'accent',
},
{
value: '2',
label: 'Item 2 (create)',
label: 'Item 2',
onSelect: () => alert('Item 2 action'),
highlightColor: 'create',
},
{
value: '3',
label: 'Item 3 (destroy)',
label: 'Item 3',
onSelect: () => alert('Item 3 action'),
highlightColor: 'destroy',
},
];
return (
<StoryWrapper>
<DropdownMenu {...args} items={exampleItems}>
<DropdownMenu
{...args}
items={exampleItems}
>
<span>Menu</span>
</DropdownMenu>
</StoryWrapper>
+6 -6
View File
@@ -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-success);
['positive']: `
--item-highlighted-textColor: var(--color-positive);
`,
['destroy']: `
--item-highlighted-textColor: var(--color-error);
['negative']: `
--item-highlighted-textColor: var(--color-negative);
`,
}[$highlightColor])}
+3 -3
View File
@@ -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;
}
`;
-3
View File
@@ -13,7 +13,6 @@ import {
CaretIcon,
CautionCircleStrokeIcon,
CautionCircleIcon,
ChaosLabsIcon,
ChatIcon,
CheckIcon,
CheckCircleIcon,
@@ -91,7 +90,6 @@ export enum IconName {
Caret = 'Caret',
CautionCircle = 'CautionCircle',
CautionCircleStroked = 'CautionCircleStroked',
ChaosLabs = 'ChaosLabs',
Chat = 'Chat',
Check = 'Check',
CheckCircle = 'CheckCircle',
@@ -170,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,
@@ -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"
+1 -11
View File
@@ -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];
+3 -5
View File
@@ -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,
};
+3 -5
View File
@@ -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 ? (
+4 -10
View File
@@ -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;
@@ -513,7 +513,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()}
@@ -523,7 +523,7 @@ export const ViewMoreRow = ({ colSpan, onClick }: { colSpan: number; onClick: ()
{stringGetter({ key: STRING_KEYS.VIEW_MORE })}
</Styled.ViewMoreButton>
</Styled.Td>
</Styled.ViewMoreTr>
</Styled.Tr>
);
};
@@ -673,8 +673,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;
@@ -784,7 +782,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);
}
`};
@@ -986,7 +984,3 @@ Styled.ViewMoreButton = styled(Button)`
margin-left: 0.5ch;
}
`;
Styled.ViewMoreTr = styled(Styled.Tr)`
--border-color: var(--tableViewMore-borderColor);
`;
+2 -2
View File
@@ -117,7 +117,7 @@ Styled.ConfirmButton = styled(Styled.IconButton)`
--button-backgroundColor: hsla(203, 25%, 19%, 1);
svg {
color: var(--color-success);
color: var(--color-positive);
}
`;
@@ -125,7 +125,7 @@ Styled.CancelButton = styled(Styled.IconButton)`
--button-backgroundColor: hsla(296, 16%, 18%, 1);
svg {
color: var(--color-error);
color: var(--color-negative);
width: 0.8em;
height: 0.8em;
+1 -1
View File
@@ -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;
`;
-19
View File
@@ -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,
-3
View File
@@ -2,7 +2,6 @@ export enum DialogTypes {
ClosePosition = 'ClosePosition',
Deposit = 'Deposit',
DisconnectWallet = 'DisconnectWallet',
DisplaySettings = 'DisplaySettings',
ExchangeOffline = 'ExchangeOffline',
ExternalLink = 'ExternalLink',
FillDetails = 'FillDetails',
@@ -20,8 +19,6 @@ export enum DialogTypes {
Transfer = 'Transfer',
Withdraw = 'Withdraw',
ManageFunds = 'ManageFunds',
NewMarketMessageDetails = 'NewMarketMessageDetails',
NewMarketAgreement = 'NewMarketAgreement',
}
export enum TradeBoxDialogTypes {
-23
View File
@@ -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;
};
-1
View File
@@ -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',
+1 -1
View File
@@ -95,7 +95,7 @@ export type TooltipStrings = {
stringParams?: any;
urlConfigs?: LinksConfigs;
}) => {
title?: string;
title: string;
body: string;
learnMoreLink?: string;
};
-85
View File
@@ -1,85 +0,0 @@
export type ExchangeConfigParsedCsv = Array<{
base_asset: string;
exchange: string;
pair: string;
adjust_by_market: string;
min_2_depth: string;
avg_30d_vol: string;
reference_price: string;
risk_assessment: string;
num_oracles: string;
liquidity_tier: string;
asset_name: string;
}>;
export type ExchangeConfigItem = {
exchangeName: string;
ticker: string;
adjustByMarket?: string;
};
export type PotentialMarketParsedCsv = Array<{
base_asset: string;
reference_price: string;
num_oracles: string;
liquidity_tier: string;
asset_name: string;
p: string;
atomic_resolution: string;
min_exchanges: string;
min_price_change_ppm: string;
price_exponent: string;
step_base_quantum: string;
ticksize_exponent: string;
subticks_per_tick: string;
min_order_size: string;
quantum_conversion_exponent: string;
}>;
export type PotentialMarketItem = {
baseAsset: string;
referencePrice: string;
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;
export const LIQUIDITY_TIERS = {
0: {
label: 'Large-cap',
initialMarginFraction: 0.05,
maintenanceMarginFraction: 0.03,
impactNotional: 10_000,
},
1: {
label: 'Mid-cap',
initialMarginFraction: 0.1,
maintenanceMarginFraction: 0.05,
impactNotional: 5_000,
},
2: {
label: 'Long-tail',
initialMarginFraction: 0.2,
maintenanceMarginFraction: 0.1,
impactNotional: 2_500,
},
3: {
label: 'Safety',
initialMarginFraction: 1,
maintenanceMarginFraction: 0.2,
impactNotional: 2_500,
},
};
-4
View File
@@ -11,10 +11,6 @@ export enum AppRoute {
Privacy = '/privacy',
}
export enum MarketsRoute {
New = 'new',
}
export enum PortfolioRoute {
Fees = 'fees',
History = 'history',
-6
View File
@@ -68,9 +68,3 @@ export enum OpacityToken {
Opacity66 = 'A8',
Opacity90 = 'E6',
}
export enum BrightnessFilterToken {
Darken10 = '0.9',
Darken5 = '0.95',
Lighten10 = '1.1',
}
+2 -23
View File
@@ -1,11 +1,4 @@
import { AppColorMode } from '@/state/configs';
export type Theme = {
[AppColorMode.GreenUp]: ThemeColorBase;
[AppColorMode.RedUp]: ThemeColorBase;
};
export type ThemeColorBase = LayerColors &
export type ThemeColors = LayerColors &
BorderColors &
TextColors &
GradientColors &
@@ -14,8 +7,7 @@ export type ThemeColorBase = LayerColors &
DirectionalColors &
RiskColors &
IconColors &
ComponentColors &
Filters;
ComponentColors;
type LayerColors = {
layer0: string;
@@ -38,8 +30,6 @@ type TextColors = {
textPrimary: string;
textSecondary: string;
textTertiary: string;
textButton: string;
};
type GradientColors = {
@@ -57,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;
@@ -90,9 +75,3 @@ type ComponentColors = {
toggleBackground: string;
tooltipBackground: string;
};
type Filters = {
hoverFilterBase: string;
hoverFilterVariant: string;
activeFilter: string;
};
+2 -8
View File
@@ -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 }),
@@ -162,10 +163,6 @@ export const tradeTooltips: TooltipStrings = {
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 +195,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;
+3 -3
View File
@@ -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
-4
View File
@@ -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,
+3 -11
View File
@@ -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 };
};
+4 -19
View File
@@ -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]);
};
+16
View File
@@ -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];
}
-48
View File
@@ -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];
};
+5 -43
View File
@@ -1,6 +1,5 @@
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import {
BECH32_PREFIX,
CompositeClient,
@@ -10,7 +9,6 @@ import {
onboarding,
Network,
ValidatorConfig,
type ProposalStatus,
} from '@dydxprotocol/v4-client-js';
import type { ResolutionString } from 'public/tradingview/charting_library';
@@ -70,21 +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,
}
)
}, {
broadcastPollIntervalMs: 3_000,
broadcastTimeoutMs: 60_000,
})
)
);
setCompositeClient(initializedClient);
@@ -117,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,
@@ -261,8 +225,6 @@ const useDydxClientContext = () => {
getWalletFromEvmSignature,
// Public Methods
requestAllPerpetualMarkets,
requestAllGovernanceProposals,
getCandlesForDatafeed,
screenAddresses,
};
-16
View File
@@ -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;
};
-118
View File
@@ -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,
};
};
-62
View File
@@ -1,62 +0,0 @@
import { createContext, useContext, useEffect, useState } from 'react';
import type {
ExchangeConfigItem,
ExchangeConfigParsedCsv,
PotentialMarketItem,
PotentialMarketParsedCsv,
} from '@/constants/potentialMarkets';
import { log } from '@/lib/telemetry';
const PotentialMarketsContext = createContext<ReturnType<typeof usePotentialMarketsContext>>({
potentialMarkets: undefined,
exchangeConfigs: undefined,
hasPotentialMarketsData: false,
});
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 [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);
}
}, []);
return {
potentialMarkets,
exchangeConfigs,
hasPotentialMarketsData: Boolean(potentialMarkets && exchangeConfigs),
};
};
+12 -43
View File
@@ -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 -13
View File
@@ -115,15 +115,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 });
@@ -151,6 +143,9 @@ export const useWalletConnection = () => {
} 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({
@@ -200,9 +195,6 @@ export const useWalletConnection = () => {
try {
const { walletType, walletConnectionType } = await connectWallet({
walletType: selectedWalletType,
isAccountConnected: Boolean(
evmAddress && evmDerivedAddresses[evmAddress]?.encryptedSignature
),
});
setWalletType(walletType);
@@ -225,7 +217,7 @@ export const useWalletConnection = () => {
await disconnectWallet();
}
})();
}, [selectedWalletType, signerWagmi, signerGraz, evmDerivedAddresses, evmAddress]);
}, [selectedWalletType, signerWagmi, signerGraz]);
const selectWalletType = async (walletType: WalletType | undefined) => {
if (selectedWalletType) {
-62
View File
@@ -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
fill-rule="evenodd"
clip-rule="evenodd"
d="M47.6624 4.38721C46.5167 4.38721 45.5396 4.77222 44.7521 5.54468C43.9625 6.31199 43.5687 7.27749 43.5687 8.41904C43.5687 9.55454 43.9632 10.5194 44.7514 11.2929L44.7527 11.2939C45.5403 12.0594 46.5173 12.4406 47.6624 12.4406C48.8074 12.4406 49.7845 12.0594 50.572 11.2939L50.5734 11.2929C51.3616 10.5194 51.756 9.55454 51.756 8.41904C51.756 7.27749 51.3623 6.312 50.5727 5.54469C49.7851 4.77223 48.8081 4.38721 47.6624 4.38721ZM45.4207 8.41904C45.4207 7.76676 45.6364 7.22501 46.0671 6.77549C46.5039 6.32689 47.0294 6.10561 47.6624 6.10561C48.2954 6.10561 48.8168 6.32697 49.2462 6.77466L49.2476 6.77617C49.6857 7.22615 49.9034 7.7677 49.9034 8.41904C49.9034 9.06265 49.6864 9.60104 49.2476 10.0516L49.2462 10.0531C48.8168 10.5008 48.2954 10.7222 47.6624 10.7222C47.0294 10.7222 46.5039 10.5009 46.0671 10.0523C45.6357 9.60218 45.4207 9.06359 45.4207 8.41904Z"
fill={fills[1]}
/>
<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
fill-rule="evenodd"
clip-rule="evenodd"
d="M40.3586 4.56055H38.6659L35.2261 12.3667H37.1862L37.9072 10.7289H41.1173L41.8383 12.3667H43.7984L40.3586 4.56055ZM38.6686 9.00014L39.5126 7.08737L40.3559 9.00014H38.6686Z"
fill={fills[1]}
/>
</svg>
);
};
export default ChaosLabsIcon;
+1 -1
View File
@@ -1,3 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.98083 12.9826C2.41272 13.2911 1.68993 13.0863 1.36776 12.5275L0.759291 11.4721C0.436526 10.9122 0.620013 10.1856 1.1752 9.84545L1.55868 9.61048C1.7994 9.46299 1.99441 9.11427 1.99426 8.83155L1.99336 7.16756C1.99321 6.88486 1.79835 6.53637 1.55722 6.38862L1.17373 6.15365C0.621247 5.81513 0.435901 5.08599 0.758416 4.52738L1.36754 3.47235C1.69065 2.91271 2.41137 2.70816 2.98358 3.01889L3.37882 3.23351C3.62692 3.36824 4.02656 3.36298 4.27147 3.22176L5.71299 2.39053C5.95788 2.24932 6.16238 1.90653 6.16977 1.62385L6.18152 1.17426C6.19844 0.526553 6.73722 0.00115865 7.38226 0.000757669L8.60051 2.31805e-07C9.24674 -0.000401478 9.78426 0.521358 9.80119 1.1694L9.81302 1.62228C9.8204 1.90461 10.0249 2.24808 10.2698 2.38946L11.7111 3.22163C11.956 3.363 12.3553 3.36858 12.6039 3.23358L13.002 3.01739C13.5701 2.70889 14.2929 2.91369 14.6151 3.47251L15.2235 4.52792C15.5463 5.08777 15.3628 5.81437 14.8076 6.15455L14.4241 6.38952C14.1834 6.53701 13.9884 6.88573 13.9886 7.16845L13.9895 8.83244C13.9896 9.11514 14.1845 9.46364 14.4256 9.61138L14.8091 9.84636C15.3616 10.1849 15.5469 10.914 15.2244 11.4726L14.6153 12.5277C14.2922 13.0873 13.5715 13.2918 12.9992 12.9811L12.604 12.7665C12.3559 12.6318 11.9563 12.637 11.7114 12.7782L10.2698 13.6095C10.0249 13.7507 9.82045 14.0935 9.81306 14.3762L9.80132 14.8257C9.78439 15.4734 9.24561 15.9988 8.60057 15.9992L7.38232 16C6.73609 16.0004 6.19858 15.4786 6.18164 14.8306L6.16981 14.3777C6.16243 14.0954 5.95796 13.7519 5.71307 13.6105L4.27172 12.7784C4.02685 12.637 3.62756 12.6314 3.37895 12.7664L2.98083 12.9826ZM6.23556 11.0412C7.91519 12.011 10.0629 11.4355 11.0326 9.75585C12.0024 8.07623 11.4269 5.92851 9.74727 4.95878C8.06765 3.98905 5.91992 4.56453 4.95019 6.24415C3.98046 7.92377 4.55594 10.0715 6.23556 11.0412Z" fill="currentColor"/>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

+1 -3
View File
@@ -1,4 +1,3 @@
import ChaosLabsIcon from './chaos-labs';
export { default as AddressConnectorIcon } from './address-connector.svg';
export { default as ArrowIcon } from './arrow.svg';
export { default as Bar3Icon } from './bar3.svg';
@@ -35,6 +34,7 @@ export { default as HistoryIcon } from './history.svg';
export { default as LeaderboardIcon } from './leaderboard.svg';
export { default as LinkOutIcon } from './link-out.svg';
export { default as LockIcon } from './lock.svg';
export { default as LogoShortIcon } from './logo-short';
export { default as MarketsIcon } from './markets.svg';
export { default as MenuIcon } from './menu.svg';
export { default as MigrateIcon } from './migrate.svg';
@@ -90,9 +90,7 @@ export { default as WebsiteIcon } from './website.svg';
export { default as WhitepaperIcon } from './whitepaper.svg';
// Logos
export { default as ChaosLabsIcon } from './chaos-labs';
export { default as EtherscanIcon } from './logos/etherscan.svg';
export { default as LogoShortIcon } from './logo-short';
// Trade
export { default as OrderCanceledIcon } from './trade/order-canceled.svg';
+2 -2
View File
@@ -1,7 +1,7 @@
import { useAppThemeAndColorModeContext } from '@/hooks/useAppThemeAndColorMode';
import { useAppThemeContext } from '@/hooks/useAppTheme';
const LogoShortIcon: React.FC<{ id?: string }> = ({ id }: { id?: string }) => {
const theme = useAppThemeAndColorModeContext();
const theme = useAppThemeContext();
const fill = theme.logoFill;
return (
+1 -1
View File
@@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z" />
</svg>

Before

Width:  |  Height:  |  Size: 364 B

After

Width:  |  Height:  |  Size: 380 B

+2 -2
View File
@@ -1,3 +1,3 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M11 1V3.5M18.0711 3.92889L16.3033 5.69667M21 11H18.5M18.0711 18.0711L16.3033 16.3033M11 18.5V21M5.69667 16.3033L3.92889 18.0711M3.5 11H1M5.69667 5.69667L3.92889 3.92889M15.1667 11C15.1667 12.1051 14.7277 13.1649 13.9463 13.9463C13.1649 14.7277 12.1051 15.1667 11 15.1667C9.89493 15.1667 8.83512 14.7277 8.05372 13.9463C7.27232 13.1649 6.83333 12.1051 6.83333 11C6.83333 9.89493 7.27232 8.83512 8.05372 8.05372C8.83512 7.27232 9.89493 6.83333 11 6.83333C12.1051 6.83333 13.1649 7.27232 13.9463 8.05372C14.7277 8.83512 15.1667 9.89493 15.1667 11Z"/>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z" />
</svg>

Before

Width:  |  Height:  |  Size: 750 B

After

Width:  |  Height:  |  Size: 393 B

-6
View File
@@ -9,7 +9,6 @@ import { getActiveDialog } from '@/state/dialogsSelectors';
import { ClosePositionDialog } from '@/views/dialogs/ClosePositionDialog';
import { DepositDialog } from '@/views/dialogs/DepositDialog';
import { DisconnectDialog } from '@/views/dialogs/DisconnectDialog';
import { DisplaySettingsDialog } from '@/views/dialogs/DisplaySettingsDialog';
import { ExchangeOfflineDialog } from '@/views/dialogs/ExchangeOfflineDialog';
import { HelpDialog } from '@/views/dialogs/HelpDialog';
import { ExternalLinkDialog } from '@/views/dialogs/ExternalLinkDialog';
@@ -28,8 +27,6 @@ import { ManageFundsDialog } from '@/views/dialogs/ManageFundsDialog';
import { OrderDetailsDialog } from '@/views/dialogs/DetailsDialog/OrderDetailsDialog';
import { FillDetailsDialog } from '@/views/dialogs/DetailsDialog/FillDetailsDialog';
import { NewMarketMessageDetailsDialog } from '@/views/dialogs/NewMarketMessageDetailsDialog';
import { NewMarketAgreementDialog } from '@/views/dialogs/NewMarketAgreementDialog';
export const DialogManager = () => {
const dispatch = useDispatch();
@@ -52,7 +49,6 @@ export const DialogManager = () => {
return {
[DialogTypes.ClosePosition]: <ClosePositionDialog {...modalProps} />,
[DialogTypes.Deposit]: <DepositDialog {...modalProps} />,
[DialogTypes.DisplaySettings]: <DisplaySettingsDialog {...modalProps} />,
[DialogTypes.DisconnectWallet]: <DisconnectDialog {...modalProps} />,
[DialogTypes.ExchangeOffline]: <ExchangeOfflineDialog {...modalProps} />,
[DialogTypes.FillDetails]: <FillDetailsDialog {...modalProps} />,
@@ -71,7 +67,5 @@ export const DialogManager = () => {
[DialogTypes.Transfer]: <TransferDialog {...modalProps} />,
[DialogTypes.Withdraw]: <WithdrawDialog {...modalProps} />,
[DialogTypes.ManageFunds]: <ManageFundsDialog {...modalProps} />,
[DialogTypes.NewMarketMessageDetails]: <NewMarketMessageDetailsDialog {...modalProps} />,
[DialogTypes.NewMarketAgreement]: <NewMarketAgreementDialog {...modalProps} />,
}[type];
};
+1 -1
View File
@@ -127,7 +127,7 @@ Styled.StatusDot = styled.div<{ exchangeStatus: ExchangeStatus }>`
background-color: ${({ exchangeStatus }) =>
({
[ExchangeStatus.Degraded]: css`var(--color-warning)`,
[ExchangeStatus.Operational]: css`var(--color-success)`,
[ExchangeStatus.Operational]: css`var(--color-positive)`,
}[exchangeStatus])};
`;
+2 -15
View File
@@ -3,8 +3,6 @@ import type { LocalWallet } from '@dydxprotocol/v4-client-js';
import type {
ClosePositionInputFields,
Nullable,
HistoricalTradingRewardsPeriod,
HistoricalTradingRewardsPeriods,
HumanReadablePlaceOrderPayload,
HumanReadableCancelOrderPayload,
TradeInputFields,
@@ -25,7 +23,6 @@ import {
CoroutineTimer,
TransferType,
AbacusAppConfig,
ApiData,
} from '@/constants/abacus';
import { DEFAULT_MARKETID } from '@/constants/markets';
@@ -36,6 +33,8 @@ import type { RootStore } from '@/state/_store';
import { setTradeFormInputs } from '@/state/inputs';
import { getInputTradeOptions, getTransferInputs } from '@/state/inputsSelectors';
import { testFlags } from '@/lib/testFlags';
import AbacusRest from './rest';
import AbacusAnalytics from './analytics';
import AbacusWebsocket from './websocket';
@@ -228,15 +227,6 @@ class AbacusStateManager {
this.stateManager.historicalPnlPeriod = period;
};
setHistoricalTradingRewardPeriod = (
period: (typeof HistoricalTradingRewardsPeriod)[keyof typeof HistoricalTradingRewardsPeriod]
) => {
this.stateManager.historicalTradingRewardPeriod = period;
};
refreshHistoricalTradingRewards = () =>
this.stateManager.refresh(ApiData.HISTORICAL_TRADING_REWARDS);
switchNetwork = (network: DydxNetwork) => {
this.stateManager.environmentId = network;
@@ -288,9 +278,6 @@ class AbacusStateManager {
getHistoricalPnlPeriod = (): Nullable<HistoricalPnlPeriods> =>
this.stateManager.historicalPnlPeriod;
getHistoricalTradingRewardPeriod = (): HistoricalTradingRewardsPeriods =>
this.stateManager.historicalTradingRewardPeriod;
handleCandlesSubscription = ({
channelId,
subscribe,
-7
View File
@@ -29,7 +29,6 @@ import {
setSubaccount,
setTransfers,
setWallet,
setTradingRewards,
} from '@/state/account';
import { setApiState } from '@/state/app';
@@ -97,12 +96,6 @@ class AbacusStateNotifier implements AbacusStateNotificationProtocol {
}
}
if (changes.has(Changes.tradingRewards)) {
if (updatedState.account?.tradingRewards) {
dispatch(setTradingRewards(updatedState.account?.tradingRewards));
}
}
if (changes.has(Changes.configs)) {
dispatch(setConfigs(updatedState.configs));
}
+3 -3
View File
@@ -43,19 +43,19 @@ export const getStatusIconInfo = ({
case AbacusOrderStatus.filled: {
return {
statusIcon: IconName.OrderFilled,
statusIconColor: `var(--color-success)`,
statusIconColor: `var(--color-positive)`,
};
}
case AbacusOrderStatus.cancelled: {
return {
statusIcon: IconName.OrderCanceled,
statusIconColor: `var(--color-error)`,
statusIconColor: `var(--color-negative)`,
};
}
case AbacusOrderStatus.canceling: {
return {
statusIcon: IconName.OrderPending,
statusIconColor: `var(--color-error)`,
statusIconColor: `var(--color-negative)`,
};
}
case AbacusOrderStatus.untriggered: {
-4
View File
@@ -26,10 +26,6 @@ class TestFlags {
get addressOverride():string {
return this.queryParams.address;
}
get showTradingRewards() {
return !!this.queryParams.tradingrewards;
}
}
export const testFlags = new TestFlags();
+3 -9
View File
@@ -1,6 +1,6 @@
import { Candle, TradingViewBar, TradingViewSymbol } from '@/constants/candles';
import type { AppTheme, AppColorMode } from '@/state/configs';
import { AppTheme } from '@/state/configs';
import { Themes } from '@/styles/themes';
@@ -47,14 +47,8 @@ export const getHistorySlice = ({
return bars.filter(({ time }) => time >= fromMs);
};
export const getWidgetOverrides = ({
appTheme,
appColorMode,
}: {
appTheme: AppTheme;
appColorMode: AppColorMode;
}) => {
const theme = Themes[appTheme][appColorMode];
export const getWidgetOverrides = (appTheme: AppTheme) => {
const theme = Themes[appTheme];
return {
overrides: {
+73 -113
View File
@@ -23,10 +23,7 @@ import { AppRoute, PortfolioRoute, HistoryRoute } from '@/constants/routes';
import { wallets } from '@/constants/wallets';
import { useAccounts, useStringGetter, useTokenConfigs } from '@/hooks';
import {
getHistoricalTradingRewardsForCurrentWeek,
getOnboardingState,
} from '@/state/accountSelectors';
import { getOnboardingState } from '@/state/accountSelectors';
import { openDialog } from '@/state/dialogs';
import { isTruthy } from '@/lib/isTruthy';
@@ -55,8 +52,6 @@ const Profile = () => {
chainId: ENS_CHAIN_ID,
});
const currentWeekTradingReward = useSelector(getHistoricalTradingRewardsForCurrentWeek);
const actions = [
{
key: 'deposit',
@@ -164,62 +159,64 @@ const Profile = () => {
);
})}
</Styled.Actions>
<Styled.SettingsButton
slotHeader={
<Styled.InlineRow>
<Icon iconName={IconName.Gear} />
{stringGetter({ key: STRING_KEYS.SETTINGS })}
</Styled.InlineRow>
}
onClick={() => navigate(AppRoute.Settings)}
/>
<Styled.HelpButton
slotHeader={
<Styled.InlineRow>
<Icon iconName={IconName.HelpCircle} />
{stringGetter({ key: STRING_KEYS.HELP })}
</Styled.InlineRow>
}
onClick={() => dispatch(openDialog({ type: DialogTypes.Help }))}
/>
<Styled.MigratePanel />
<Styled.DYDXBalancePanel />
<Styled.RewardsPanel
slotHeaderContent={stringGetter({ key: STRING_KEYS.TRADING_REWARDS })}
href={`/${chainTokenLabel}`}
hasSeparator
>
<Styled.Details
items={[
{
key: 'week-rewards',
label: stringGetter({ key: STRING_KEYS.THIS_WEEK }),
value: currentWeekTradingReward?.amount ?? '-',
},
]}
layout="grid"
<Styled.EqualGrid>
<Styled.PanelButton
slotHeader={
<Styled.InlineRow>
<Icon iconName={IconName.Gear} />
{stringGetter({ key: STRING_KEYS.SETTINGS })}
</Styled.InlineRow>
}
onClick={() => navigate(AppRoute.Settings)}
/>
</Styled.RewardsPanel>
<Styled.FeesPanel
slotHeaderContent={stringGetter({ key: STRING_KEYS.FEES })}
href={`${AppRoute.Portfolio}/${PortfolioRoute.Fees}`}
hasSeparator
>
<Styled.Details
items={[
{ key: 'maker', label: stringGetter({ key: STRING_KEYS.MAKER }), value: '-' },
{ key: 'taker', label: stringGetter({ key: STRING_KEYS.TAKER }), value: '-' },
{ key: 'volume', label: stringGetter({ key: STRING_KEYS.VOLUME_30D }), value: '-' },
]}
layout="grid"
<Styled.PanelButton
slotHeader={
<Styled.InlineRow>
<Icon iconName={IconName.HelpCircle} />
{stringGetter({ key: STRING_KEYS.HELP })}
</Styled.InlineRow>
}
onClick={() => dispatch(openDialog({ type: DialogTypes.Help }))}
/>
</Styled.FeesPanel>
</Styled.EqualGrid>
<Styled.HistoryPanel
<MigratePanel />
<DYDXBalancePanel />
<Styled.EqualGrid>
<Styled.RewardsPanel
slotHeaderContent="Trading Rewards"
href={`/${chainTokenLabel}`}
hasSeparator
>
<Styled.Details
items={[
{
key: 'week-rewards',
label: stringGetter({ key: STRING_KEYS.THIS_WEEK }),
value: '-',
},
]}
layout="grid"
/>
</Styled.RewardsPanel>
<Panel
slotHeaderContent={stringGetter({ key: STRING_KEYS.FEES })}
href={`${AppRoute.Portfolio}/${PortfolioRoute.Fees}`}
hasSeparator
>
<Styled.Details
items={[
{ key: 'maker', label: stringGetter({ key: STRING_KEYS.MAKER }), value: '-' },
{ key: 'taker', label: stringGetter({ key: STRING_KEYS.TAKER }), value: '-' },
{ key: 'volume', label: stringGetter({ key: STRING_KEYS.VOLUME_30D }), value: '-' },
]}
layout="grid"
/>
</Panel>
</Styled.EqualGrid>
<Styled.TablePanel
slotHeaderContent={stringGetter({ key: STRING_KEYS.HISTORY })}
href={`${AppRoute.Portfolio}/${PortfolioRoute.History}/${HistoryRoute.Trades}`}
hasSeparator
@@ -233,10 +230,10 @@ const Profile = () => {
]}
withInnerBorders={false}
/>
</Styled.HistoryPanel>
</Styled.TablePanel>
<Styled.GovernancePanel />
<Styled.StakingPanel />
<GovernancePanel />
<StakingPanel />
</Styled.MobileProfileLayout>
);
};
@@ -248,27 +245,14 @@ const Styled: Record<string, AnyStyledComponent> = {};
Styled.MobileProfileLayout = styled.div`
${layoutMixins.contentContainerPage}
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
padding: 1.25rem 0.9rem;
max-width: 100vw;
grid-template-areas:
'header header'
'actions actions'
'settings help'
'migrate migrate'
'balance balance'
'rewards fees'
'history history'
'governance governance'
'staking staking';
`;
Styled.Header = styled.header`
grid-area: header;
${layoutMixins.row}
padding: 0 1rem;
`;
@@ -302,10 +286,10 @@ Styled.ConnectedIcon = styled.div`
height: 0.5rem;
width: 0.5rem;
margin-right: 0.25rem;
background: var(--color-success);
background: var(--color-positive);
border-radius: 50%;
box-shadow: 0 0 0 0.2rem var(--color-gradient-success);
box-shadow: 0 0 0 0.2rem var(--color-gradient-positive);
`;
Styled.Address = styled.h1`
@@ -315,7 +299,6 @@ Styled.Address = styled.h1`
Styled.Actions = styled(Toolbar)`
${layoutMixins.spacedRow}
--stickyArea-topHeight: 5rem;
grid-area: actions;
> a,
> label {
@@ -335,7 +318,7 @@ Styled.ActionButton = styled(IconButton)<{ iconName?: IconName }>`
${({ iconName }) =>
iconName === IconName.Close
? css`
--button-textColor: var(--color-error);
--button-textColor: var(--color-negative);
--button-icon-size: 0.75em;
`
: iconName === IconName.Transfer &&
@@ -346,16 +329,22 @@ Styled.ActionButton = styled(IconButton)<{ iconName?: IconName }>`
`}
`;
Styled.EqualGrid = styled.div`
${layoutMixins.gridEqualColumns}
gap: 1rem;
`;
Styled.Details = styled(Details)`
font: var(--font-small-book);
--details-value-font: var(--font-medium-book);
`;
Styled.RewardsPanel = styled(Panel)`
grid-area: rewards;
align-self: flex-start;
height: 100%;
> div {
&,
> * {
height: 100%;
}
@@ -364,12 +353,7 @@ Styled.RewardsPanel = styled(Panel)`
}
`;
Styled.FeesPanel = styled(Panel)`
grid-area: fees;
`;
Styled.HistoryPanel = styled(Panel)`
grid-area: history;
Styled.TablePanel = styled(Panel)`
--panel-content-paddingY: 0;
--panel-content-paddingX: 0;
@@ -409,27 +393,3 @@ Styled.PanelButton = styled(Panel)`
--panel-paddingY: 0
--panel-paddingX:0;
`;
Styled.SettingsButton = styled(Styled.PanelButton)`
grid-area: settings;
`;
Styled.HelpButton = styled(Styled.PanelButton)`
grid-area: help;
`;
Styled.MigratePanel = styled(MigratePanel)`
grid-area: migrate;
`;
Styled.DYDXBalancePanel = styled(DYDXBalancePanel)`
grid-area: balance;
`;
Styled.GovernancePanel = styled(GovernancePanel)`
grid-area: governance;
`;
Styled.StakingPanel = styled(StakingPanel)`
grid-area: staking;
`;
+2 -13
View File
@@ -1,25 +1,21 @@
import styled, { AnyStyledComponent } from 'styled-components';
import { useNavigate } from 'react-router-dom';
import { breakpoints } from '@/styles';
import { STRING_KEYS } from '@/constants/localization';
import { AppRoute, MarketsRoute } from '@/constants/routes';
import { useBreakpoints, useDocumentTitle, useStringGetter } from '@/hooks';
import { usePotentialMarkets } from '@/hooks/usePotentialMarkets';
import { layoutMixins } from '@/styles/layoutMixins';
import { Button } from '@/components/Button';
import { ContentSectionHeader } from '@/components/ContentSectionHeader';
import { ExchangeBillboards } from '@/views/ExchangeBillboards';
import { MarketsTable } from '@/views/tables/MarketsTable';
const Markets = () => {
const stringGetter = useStringGetter();
const { isNotTablet } = useBreakpoints();
const navigate = useNavigate();
const { hasPotentialMarketsData } = usePotentialMarkets();
useDocumentTitle(stringGetter({ key: STRING_KEYS.MARKETS }));
@@ -29,13 +25,6 @@ const Markets = () => {
<Styled.ContentSectionHeader
title={stringGetter({ key: STRING_KEYS.MARKETS })}
subtitle={isNotTablet && stringGetter({ key: STRING_KEYS.DISCOVER_NEW_ASSETS })}
slotRight={
hasPotentialMarketsData && (
<Button onClick={() => navigate(`${AppRoute.Markets}/${MarketsRoute.New}`)}>
{stringGetter({ key: STRING_KEYS.ADD_A_MARKET })}
</Button>
)
}
/>
<Styled.ExchangeBillboards isSearching={false} searchQuery="" />
</Styled.HeaderSection>
-259
View File
@@ -1,259 +0,0 @@
import { useMemo, useState } from 'react';
import styled, { AnyStyledComponent } from 'styled-components';
import { useNavigate } from 'react-router-dom';
import { STRING_KEYS } from '@/constants/localization';
import { isMainnet } from '@/constants/networks';
import { AppRoute } from '@/constants/routes';
import {
useBreakpoints,
useDocumentTitle,
useGovernanceVariables,
useStringGetter,
useTokenConfigs,
} from '@/hooks';
import { breakpoints } from '@/styles';
import { layoutMixins } from '@/styles/layoutMixins';
import { Button } from '@/components/Button';
import { ContentSectionHeader } from '@/components/ContentSectionHeader';
import { IconButton } from '@/components/IconButton';
import { Icon, IconName } from '@/components/Icon';
import { Link } from '@/components/Link';
import { NewMarketForm } from '@/views/forms/NewMarketForm';
import { MustBigNumber } from '@/lib/numbers';
const StepItem = ({ step, subtitle, title }: { step: number; subtitle: string; title: string }) => (
<Styled.StepItem>
<Styled.StepNumber>{step}</Styled.StepNumber>
<Styled.Column>
<Styled.Title>{title}</Styled.Title>
<Styled.Subtitle>{subtitle}</Styled.Subtitle>
</Styled.Column>
</Styled.StepItem>
);
const NewMarket = () => {
const { isNotTablet } = useBreakpoints();
const { newMarketProposal } = useGovernanceVariables();
const navigate = useNavigate();
const [displaySteps, setDisplaySteps] = useState(true);
const stringGetter = useStringGetter();
const { chainTokenLabel, chainTokenDecimals } = useTokenConfigs();
useDocumentTitle(stringGetter({ key: STRING_KEYS.ADD_A_MARKET }));
const steps = useMemo(() => {
return [
{
step: 1,
title: stringGetter({ key: STRING_KEYS.ADD_MARKET_STEP_1_TITLE }),
subtitle: stringGetter({
key: STRING_KEYS.ADD_MARKET_STEP_1_DESCRIPTION,
params: {
HERE: (
<Styled.Link href={newMarketProposal.newMarketsMethodology}>
{stringGetter({ key: STRING_KEYS.HERE })}
</Styled.Link>
),
},
}),
},
{
step: 2,
title: stringGetter({ key: STRING_KEYS.ADD_MARKET_STEP_2_TITLE }),
subtitle: stringGetter({ key: STRING_KEYS.ADD_MARKET_STEP_2_DESCRIPTION }),
},
{
step: 3,
title: stringGetter({ key: STRING_KEYS.ADD_MARKET_STEP_3_TITLE }),
subtitle: stringGetter({
key: STRING_KEYS.ADD_MARKET_STEP_3_DESCRIPTION,
params: {
REQUIRED_NUM_TOKENS: MustBigNumber(newMarketProposal?.initialDepositAmount)
.div(Number(`1e${chainTokenDecimals}`))
.toFixed(isMainnet ? 0 : chainTokenDecimals),
NATIVE_TOKEN_DENOM: chainTokenLabel,
},
}),
},
];
}, [stringGetter, newMarketProposal, chainTokenLabel]);
return (
<Styled.Page>
<Styled.HeaderSection>
<Styled.ContentSectionHeader
title={stringGetter({ key: STRING_KEYS.SUGGEST_NEW_MARKET })}
slotRight={
<IconButton iconName={IconName.Close} onClick={() => navigate(AppRoute.Markets)} />
}
subtitle={isNotTablet && stringGetter({ key: STRING_KEYS.ADD_DETAILS_TO_LAUNCH_MARKET })}
/>
</Styled.HeaderSection>
<Styled.Content>
<div>
<Button
slotLeft={<Styled.Icon iconName={displaySteps ? IconName.Hide : IconName.HelpCircle} />}
onClick={() => setDisplaySteps(!displaySteps)}
>
{displaySteps
? stringGetter({ key: STRING_KEYS.HIDE_STEPS })
: stringGetter({ key: STRING_KEYS.SHOW_STEPS })}
</Button>
{displaySteps && (
<>
<Styled.StepsTitle>
{stringGetter({ key: STRING_KEYS.STEPS_TO_CREATE })}
</Styled.StepsTitle>
{steps.map((item) => (
<StepItem
key={item.step}
step={item.step}
title={item.title}
subtitle={item.subtitle}
/>
))}
</>
)}
</div>
<Styled.FormContainer>
<NewMarketForm />
</Styled.FormContainer>
</Styled.Content>
</Styled.Page>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Page = styled.div`
${layoutMixins.contentContainerPage}
gap: 1.5rem;
> * {
--content-max-width: 80rem;
max-width: min(calc(100vw - 4rem), var(--content-max-width));
}
@media ${breakpoints.tablet} {
--stickyArea-topHeight: var(--page-header-height-mobile);
padding: 0 1rem 1rem;
> * {
max-width: calc(100vw - 2rem);
width: 100%;
}
}
`;
Styled.ContentSectionHeader = styled(ContentSectionHeader)`
@media ${breakpoints.notTablet} {
padding: 1rem 0;
}
@media ${breakpoints.tablet} {
padding: 1.25rem 0;
h3 {
font: var(--font-extra-medium);
}
}
`;
Styled.HeaderSection = styled.section`
${layoutMixins.contentSectionDetached}
@media ${breakpoints.tablet} {
${layoutMixins.flexColumn}
gap: 1rem;
margin-bottom: 0.5rem;
}
`;
Styled.Content = styled.div`
display: flex;
flex-direction: row;
gap: 2rem;
margin: 0 auto;
@media ${breakpoints.tablet} {
display: flex;
flex-direction: column;
gap: 1rem;
margin: 0 auto;
}
`;
Styled.StepsTitle = styled.h2`
font: var(--font-large-medium);
color: var(--color-text-2);
margin: 1rem;
@media ${breakpoints.tablet} {
margin: 1rem 0;
}
`;
Styled.Icon = styled(Icon)`
margin-right: 0.5ch;
`;
Styled.StepItem = styled.div`
display: flex;
flex-direction: row;
gap: 1rem;
align-items: center;
margin-bottom: 1rem;
`;
Styled.StepNumber = styled.div`
width: 2.5rem;
height: 2.5rem;
min-width: 2.5rem;
min-height: 2.5rem;
border-radius: 50%;
background-color: var(--color-layer-5);
display: flex;
align-items: center;
justify-content: center;
color: var(--color-text-2);
`;
Styled.Column = styled.div`
display: flex;
flex-direction: column;
`;
Styled.Title = styled.span`
color: var(--color-text-2);
font: var(--font-medium-book);
`;
Styled.Subtitle = styled.span`
color: var(--color-text-0);
`;
Styled.Link = styled(Link)`
--link-color: var(--color-accent);
display: inline-block;
`;
Styled.FormContainer = styled.div`
min-width: 31.25rem;
height: fit-content;
border-radius: 1rem;
background-color: var(--color-layer-3);
padding: 1rem;
@media ${breakpoints.tablet} {
width: 100%;
min-width: unset;
}
`;
export default NewMarket;
@@ -272,7 +272,7 @@ Styled.AccountDetail = styled.div<{ gridArea: string }>`
Styled.PnlChart = styled(PnlChart)<{ pnlDiffSign: NumberSign }>`
grid-area: Chart;
background-color: var(--color-layer-2);
background-color: var(--color-layer-1);
--pnl-line-color: ${({ pnlDiffSign }) =>
({
+1 -2
View File
@@ -22,7 +22,7 @@ import { OnboardingTriggerButton } from '@/views/dialogs/OnboardingTriggerButton
import { openDialog } from '@/state/dialogs';
import { calculateCanAccountTrade } from '@/state/accountCalculators';
export const DYDXBalancePanel = ({ className }: { className?: string }) => {
export const DYDXBalancePanel = () => {
const dispatch = useDispatch();
const stringGetter = useStringGetter();
@@ -33,7 +33,6 @@ export const DYDXBalancePanel = ({ className }: { className?: string }) => {
return (
<Panel
className={className}
slotHeader={
<Styled.Header>
<Styled.Title>
+11 -13
View File
@@ -7,8 +7,6 @@ import { STRING_KEYS } from '@/constants/localization';
import { ButtonAction } from '@/constants/buttons';
import { DialogTypes } from '@/constants/dialogs';
import { ChaosLabsIcon } from '@/icons';
import breakpoints from '@/styles/breakpoints';
import { useAccounts, useBreakpoints, useStringGetter } from '@/hooks';
@@ -116,9 +114,7 @@ const LaunchIncentivesContent = () => {
<Styled.Description>
{stringGetter({ key: STRING_KEYS.LAUNCH_INCENTIVES_DESCRIPTION })}{' '}
</Styled.Description>
<Styled.ChaosLabsLogo>
{stringGetter({ key: STRING_KEYS.POWERED_BY_ALL_CAPS })} <ChaosLabsIcon />
</Styled.ChaosLabsLogo>
<Styled.ChaosLabsLogo src="/logos/chaos-labs.svg" />
<Styled.ButtonRow>
<Styled.AboutButton
action={ButtonAction.Base}
@@ -130,7 +126,7 @@ const LaunchIncentivesContent = () => {
})
);
}}
slotRight={<Icon iconName={IconName.LinkOut} />}
slotRight={<Styled.LinkOutIcon iconName={IconName.LinkOut} />}
>
{stringGetter({ key: STRING_KEYS.ABOUT })}
</Styled.AboutButton>
@@ -144,7 +140,7 @@ const LaunchIncentivesContent = () => {
})
);
}}
slotRight={<Icon iconName={IconName.LinkOut} />}
slotRight={<Styled.LinkOutIcon iconName={IconName.LinkOut} />}
slotLeft={<Icon iconName={IconName.Leaderboard} />}
>
{stringGetter({ key: STRING_KEYS.LEADERBOARD })}
@@ -157,7 +153,7 @@ const LaunchIncentivesContent = () => {
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Panel = styled(Panel)`
background-color: var(--color-layer-3);
background-color: var(--color-layer-4);
width: 100%;
`;
@@ -204,6 +200,10 @@ Styled.Button = styled(Button)`
--button-padding: 0 1rem;
`;
Styled.LinkOutIcon = styled(Icon)`
color: var(--color-text-1);
`;
Styled.AboutButton = styled(Styled.Button)`
--button-textColor: var(--color-text-2);
--button-backgroundColor: var(--color-layer-6);
@@ -280,11 +280,9 @@ Styled.Image = styled.img`
height: auto;
`;
Styled.ChaosLabsLogo = styled.span`
display: flex;
align-items: center;
gap: 0.5em;
font: var(--font-tiny-medium);
Styled.ChaosLabsLogo = styled.img`
height: 1.25rem;
align-self: start;
`;
Styled.NewTag = styled(Tag)`
-103
View File
@@ -1,103 +0,0 @@
import styled, { AnyStyledComponent } from 'styled-components';
import { useNavigate } from 'react-router-dom';
import { ButtonAction, ButtonSize } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization';
import { isMainnet } from '@/constants/networks';
import { AppRoute, MarketsRoute } from '@/constants/routes';
import { useStringGetter, useTokenConfigs } from '@/hooks';
import { usePotentialMarkets } from '@/hooks/usePotentialMarkets';
import { useGovernanceVariables } from '@/hooks/useGovernanceVariables';
import { Panel } from '@/components/Panel';
import { IconName } from '@/components/Icon';
import { IconButton } from '@/components/IconButton';
import { Output, OutputType } from '@/components/Output';
import { Tag } from '@/components/Tag';
import { MustBigNumber } from '@/lib/numbers';
import { layoutMixins } from '@/styles/layoutMixins';
export const NewMarketsPanel = () => {
const stringGetter = useStringGetter();
const navigate = useNavigate();
const { hasPotentialMarketsData } = usePotentialMarkets();
const { chainTokenDecimals, chainTokenLabel } = useTokenConfigs();
const { newMarketProposal } = useGovernanceVariables();
const initialDepositAmountBN = MustBigNumber(newMarketProposal.initialDepositAmount).div(
Number(`1e${chainTokenDecimals}`)
);
const initialDepositAmountDecimals = isMainnet ? 0 : chainTokenDecimals;
if (!hasPotentialMarketsData) return null;
return (
<Panel
slotHeaderContent={
<Styled.Title>
{stringGetter({ key: STRING_KEYS.ADD_A_MARKET })}
<Styled.NewTag>{stringGetter({ key: STRING_KEYS.NEW })}</Styled.NewTag>
</Styled.Title>
}
slotRight={
<Styled.Arrow>
<Styled.IconButton
action={ButtonAction.Base}
iconName={IconName.Arrow}
size={ButtonSize.Small}
/>
</Styled.Arrow>
}
onClick={() => navigate(`${AppRoute.Markets}/${MarketsRoute.New}`)}
>
<Styled.Description>
{stringGetter({
key: STRING_KEYS.NEW_MARKET_REWARDS_ENTRY_DESCRIPTION,
params: {
REQUIRED_NUM_TOKENS: (
<Styled.Output
useGrouping
type={OutputType.Number}
value={initialDepositAmountBN}
fractionDigits={initialDepositAmountDecimals}
/>
),
NATIVE_TOKEN_DENOM: chainTokenLabel,
},
})}
</Styled.Description>
</Panel>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Description = styled.div`
color: var(--color-text-0);
`;
Styled.IconButton = styled(IconButton)`
color: var(--color-text-0);
--color-border: var(--color-layer-6);
`;
Styled.Arrow = styled.div`
padding-right: 1.5rem;
`;
Styled.Title = styled.h3`
font: var(--font-medium-book);
color: var(--color-text-2);
margin-bottom: -1rem;
${layoutMixins.inlineRow}
`;
Styled.Output = styled(Output)`
display: inline-block;
`;
Styled.NewTag = styled(Tag)`
color: var(--color-accent);
background-color: var(--color-accent-faded);
`;
-105
View File
@@ -1,105 +0,0 @@
import { useCallback, useState } from 'react';
import styled, { AnyStyledComponent } from 'styled-components';
import { useStringGetter } from '@/hooks';
import {
HISTORICAL_TRADING_REWARDS_PERIODS,
HistoricalTradingRewardsPeriod,
HistoricalTradingRewardsPeriods,
} from '@/constants/abacus';
import { STRING_KEYS } from '@/constants/localization';
import breakpoints from '@/styles/breakpoints';
import { layoutMixins } from '@/styles/layoutMixins';
import { Panel } from '@/components/Panel';
import { ToggleGroup } from '@/components/ToggleGroup';
import { WithTooltip } from '@/components/WithTooltip';
import { TradingRewardHistoryTable } from '@/views/tables/TradingRewardHistoryTable';
import abacusStateManager from '@/lib/abacus';
export const RewardHistoryPanel = () => {
const stringGetter = useStringGetter();
const [selectedPeriod, setSelectedPeriod] = useState<HistoricalTradingRewardsPeriods>(
abacusStateManager.getHistoricalTradingRewardPeriod() || HistoricalTradingRewardsPeriod.WEEKLY
);
const onSelectPeriod = useCallback(
(periodName: string) => {
const selectedPeriod =
HISTORICAL_TRADING_REWARDS_PERIODS[
periodName as keyof typeof HISTORICAL_TRADING_REWARDS_PERIODS
];
setSelectedPeriod(selectedPeriod);
abacusStateManager.setHistoricalTradingRewardPeriod(selectedPeriod);
},
[setSelectedPeriod, selectedPeriod]
);
return (
<Panel
slotHeader={
<Styled.Header>
<Styled.Title>
<WithTooltip tooltip="reward-history">
<h3>{stringGetter({ key: STRING_KEYS.REWARD_HISTORY })}</h3>
</WithTooltip>
<span>{stringGetter({ key: STRING_KEYS.REWARD_HISTORY_DESCRIPTION })}</span>
</Styled.Title>
<ToggleGroup
items={[
{
value: HistoricalTradingRewardsPeriod.MONTHLY.name,
label: stringGetter({ key: STRING_KEYS.MONTHLY }),
},
{
value: HistoricalTradingRewardsPeriod.WEEKLY.name,
label: stringGetter({ key: STRING_KEYS.WEEKLY }),
},
{
value: HistoricalTradingRewardsPeriod.DAILY.name,
label: stringGetter({ key: STRING_KEYS.DAILY }),
},
]}
value={selectedPeriod.name}
onValueChange={onSelectPeriod}
/>
</Styled.Header>
}
>
<TradingRewardHistoryTable period={selectedPeriod} />
</Panel>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Header = styled.div`
${layoutMixins.spacedRow}
padding: 1rem 1rem 0;
margin-bottom: -0.5rem;
@media ${breakpoints.notTablet} {
padding: 1.25rem 1.5rem 0;
}
`;
Styled.Title = styled.div`
${layoutMixins.column}
color: var(--color-text-0);
font: var(--font-small-book);
h3 {
font: var(--font-medium-book);
color: var(--color-text-2);
}
`;
Styled.Content = styled.div`
${layoutMixins.flexColumn}
gap: 0.75rem;
`;
+15 -13
View File
@@ -29,18 +29,20 @@ export const RewardsHelpPanel = () => {
>
<Accordion
items={[
{
header: stringGetter({ key: STRING_KEYS.FAQ_WHO_IS_ELIGIBLE_QUESTION }),
content: stringGetter({ key: STRING_KEYS.FAQ_WHO_IS_ELIGIBLE_ANSWER }),
},
{
header: stringGetter({ key: STRING_KEYS.FAQ_HOW_DO_TRADING_REWARDS_WORK_QUESTION }),
content: stringGetter({ key: STRING_KEYS.FAQ_HOW_DO_TRADING_REWARDS_WORK_ANSWER }),
},
{
header: stringGetter({ key: STRING_KEYS.FAQ_HOW_DO_I_CLAIM_MY_REWARDS_QUESTION }),
content: stringGetter({ key: STRING_KEYS.FAQ_HOW_DO_I_CLAIM_MY_REWARDS_ANSWER }),
},
{
header: 'Who is eligible for trading rewards?',
content: 'All traders are eligible for trading rewards.',
},
{
header: 'How do trading rewards work?',
content:
'Immediately after each fill, trading rewards are sent directly to the traders dYdX Chain address, based on the amount of fees paid by the trader.',
},
{
header: 'How do I claim my rewards?',
content:
'Each block, trading rewards are automatically sent directly to the traders dYdX Chain address.',
},
]}
/>
</Styled.HelpCard>
@@ -70,7 +72,7 @@ Styled.Header = styled.div`
font: var(--font-small-book);
@media ${breakpoints.notTablet} {
padding: 1.5rem;
padding: 1.5rem 1.25rem;
}
h3 {
+32 -117
View File
@@ -1,4 +1,5 @@
import styled, { AnyStyledComponent, css } from 'styled-components';
import styled, { AnyStyledComponent } from 'styled-components';
import { useDispatch } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import { STRING_KEYS } from '@/constants/localization';
@@ -10,20 +11,17 @@ import { breakpoints } from '@/styles';
import { layoutMixins } from '@/styles/layoutMixins';
import { BackButton } from '@/components/BackButton';
import { testFlags } from '@/lib/testFlags';
import { Panel } from '@/components/Panel';
import { DYDXBalancePanel } from './DYDXBalancePanel';
import { LaunchIncentivesPanel } from './LaunchIncentivesPanel';
import { MigratePanel } from './MigratePanel';
import { LaunchIncentivesPanel } from './LaunchIncentivesPanel';
import { RewardsHelpPanel } from './RewardsHelpPanel';
import { TradingRewardsSummaryPanel } from './TradingRewardsSummaryPanel';
import { RewardHistoryPanel } from './RewardHistoryPanel';
import { GovernancePanel } from './GovernancePanel';
import { StakingPanel } from './StakingPanel';
import { NewMarketsPanel } from './NewMarketsPanel';
const RewardsPage = () => {
const dispatch = useDispatch();
const stringGetter = useStringGetter();
const { isTablet, isNotTablet } = useBreakpoints();
const navigate = useNavigate();
@@ -36,38 +34,25 @@ const RewardsPage = () => {
{stringGetter({ key: STRING_KEYS.TRADING_REWARDS })}
</Styled.MobileHeader>
)}
<Styled.GridLayout
showTradingRewards={testFlags.showTradingRewards}
showMigratePanel={import.meta.env.VITE_V3_TOKEN_ADDRESS && isNotTablet}
>
{import.meta.env.VITE_V3_TOKEN_ADDRESS && isNotTablet && <Styled.MigratePanel />}
{import.meta.env.VITE_V3_TOKEN_ADDRESS && isNotTablet && <MigratePanel />}
{isTablet ? (
<Styled.LaunchIncentivesPanel />
) : (
<>
<Styled.LaunchIncentivesPanel />
<Styled.DYDXBalancePanel />
</>
)}
{isTablet ? (
<LaunchIncentivesPanel />
) : (
<Styled.PanelRowIncentivesAndBalance>
<LaunchIncentivesPanel />
<DYDXBalancePanel />
</Styled.PanelRowIncentivesAndBalance>
)}
{testFlags.showTradingRewards && (
<Styled.TradingRewardsColumn>
<TradingRewardsSummaryPanel />
{isTablet && <RewardsHelpPanel />}
<RewardHistoryPanel />
</Styled.TradingRewardsColumn>
)}
{isNotTablet && (
<Styled.PanelRow>
<GovernancePanel />
<StakingPanel />
</Styled.PanelRow>
)}
{isNotTablet && (
<Styled.OtherColumn showTradingRewards={testFlags.showTradingRewards}>
<NewMarketsPanel />
<GovernancePanel />
<StakingPanel />
<RewardsHelpPanel />
</Styled.OtherColumn>
)}
</Styled.GridLayout>
<RewardsHelpPanel />
</Styled.Page>
);
};
@@ -78,6 +63,7 @@ const Styled: Record<string, AnyStyledComponent> = {};
Styled.Page = styled.div`
${layoutMixins.contentContainerPage}
gap: 1.5rem;
padding: 2rem;
align-items: center;
@@ -102,98 +88,27 @@ Styled.MobileHeader = styled.header`
${layoutMixins.stickyHeader}
z-index: 2;
padding: 1.25rem 0;
margin-bottom: -1.5rem;
font: var(--font-large-medium);
color: var(--color-text-2);
background-color: var(--color-layer-2);
`;
Styled.GridLayout = styled.div<{ showTradingRewards?: boolean; showMigratePanel?: boolean }>`
--gap: 1.5rem;
display: grid;
grid-template-columns: 2fr 1fr;
gap: var(--gap);
Styled.Panel = styled(Panel)`
height: fit-content;
`;
> * {
gap: var(--gap);
}
${({ showTradingRewards, showMigratePanel }) =>
showTradingRewards && showMigratePanel
? css`
grid-template-areas:
'migrate migrate'
'incentives balance'
'rewards other';
`
: showTradingRewards
? css`
grid-template-areas: 'incentives balance' 'rewards other';
`
: showMigratePanel
? css`
grid-template-areas: 'migrate migrate' 'incentives balance' 'other other';
`
: css`
grid-template-areas: 'incentives balance' 'other other';
`};
Styled.PanelRow = styled.div`
${layoutMixins.gridEqualColumns}
gap: 1.5rem;
@media ${breakpoints.tablet} {
--gap: 1rem;
grid-auto-flow: row;
grid-template-columns: 1fr;
${({ showTradingRewards }) =>
showTradingRewards
? css`
grid-template-areas:
'incentives'
'rewards';
`
: css`
grid-template-areas: 'incentives';
`}
}
`;
Styled.MigratePanel = styled(MigratePanel)`
grid-area: migrate;
`;
Styled.LaunchIncentivesPanel = styled(LaunchIncentivesPanel)`
grid-area: incentives;
`;
Styled.DYDXBalancePanel = styled(DYDXBalancePanel)`
grid-area: balance;
`;
Styled.TradingRewardsColumn = styled.div`
grid-area: rewards;
${layoutMixins.flexColumn}
`;
Styled.OtherColumn = styled.div<{ showTradingRewards?: boolean }>`
grid-area: other;
${layoutMixins.flexColumn}
${({ showTradingRewards }) =>
!showTradingRewards &&
css`
display: grid;
grid-template-columns: repeat(3, 1fr);
> section:last-of-type {
grid-column: 1 / -1;
}
`}
`;
Styled.RewardHistoryHeader = styled.div`
h3 {
font: var(--font-medium-book);
color: var(--color-text-2);
}
padding: 1rem 1.5rem 0;
margin-bottom: -0.5rem;
Styled.PanelRowIncentivesAndBalance = styled(Styled.PanelRow)`
grid-template-columns: 2fr 1fr;
`;
@@ -1,134 +0,0 @@
import { useEffect } from 'react';
import styled, { AnyStyledComponent } from 'styled-components';
import { shallowEqual, useSelector } from 'react-redux';
import { STRING_KEYS } from '@/constants/localization';
import { layoutMixins } from '@/styles/layoutMixins';
import { useStringGetter, useTokenConfigs } from '@/hooks';
import { AssetIcon } from '@/components/AssetIcon';
import { Details } from '@/components/Details';
import { Output, OutputType } from '@/components/Output';
import { Panel } from '@/components/Panel';
import { getHistoricalTradingRewardsForCurrentWeek } from '@/state/accountSelectors';
import abacusStateManager from '@/lib/abacus';
export const TradingRewardsSummaryPanel = () => {
const stringGetter = useStringGetter();
const { chainTokenLabel } = useTokenConfigs();
const currentWeekTradingReward = useSelector(getHistoricalTradingRewardsForCurrentWeek, shallowEqual);
useEffect(() => {
abacusStateManager.refreshHistoricalTradingRewards();
}, []);
return !currentWeekTradingReward ? null : (
<Panel
slotHeader={
<Styled.Header>{stringGetter({ key: STRING_KEYS.TRADING_REWARDS_SUMMARY })}</Styled.Header>
}
>
<Styled.Content>
<Styled.TradingRewardsDetails
layout="grid"
items={[
{
key: 'week',
label: (
<Styled.Label>
<h4>{stringGetter({ key: STRING_KEYS.THIS_WEEK })}</h4>
</Styled.Label>
),
value: (
<Styled.Column>
<Output
slotRight={<Styled.AssetIcon symbol={chainTokenLabel} />}
type={OutputType.Asset}
value={currentWeekTradingReward.amount}
/>
<Styled.TimePeriod>
<Output
type={OutputType.Date}
value={currentWeekTradingReward.startedAtInMilliseconds}
timeOptions={{ useUTC: true }}
/>
<Output
type={OutputType.Date}
value={currentWeekTradingReward.endedAtInMilliseconds}
timeOptions={{ useUTC: true }}
/>
</Styled.TimePeriod>
</Styled.Column>
),
},
// TODO(@aforaleka): add all-time when supported
]}
/>
</Styled.Content>
</Panel>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Header = styled.div`
padding: var(--panel-paddingY) var(--panel-paddingX) 0;
font: var(--font-medium-book);
color: var(--color-text-2);
`;
Styled.Content = styled.div`
${layoutMixins.flexColumn}
gap: 0.75rem;
`;
Styled.TradingRewardsDetails = styled(Details)`
--details-item-backgroundColor: var(--color-layer-6);
grid-template-columns: 1fr; // TODO(@aforaleka): change to 1fr 1fr when all-time is supported
gap: 1rem;
> div {
gap: 0.5rem;
padding: 1rem;
border-radius: 0.75em;
background-color: var(--color-layer-5);
}
dt {
width: 100%;
}
output {
color: var(--color-text-2);
font: var(--font-large-book);
}
`;
Styled.Label = styled.div`
${layoutMixins.spacedRow}
font: var(--font-base-book);
color: var(--color-text-1);
`;
Styled.TimePeriod = styled.div`
${layoutMixins.inlineRow}
&, output {
color: var(--color-text-0);
font: var(--font-small-book);
}
`;
Styled.Column = styled.div`
${layoutMixins.flexColumn}
gap: 0.33rem;
`;
Styled.AssetIcon = styled(AssetIcon)`
margin-left: 0.5ch;
`;
-6
View File
@@ -13,7 +13,6 @@ import type {
HistoricalPnlPeriods,
SubAccountHistoricalPNLs,
UsageRestriction,
TradingRewards,
} from '@/constants/abacus';
import { OnboardingGuard, OnboardingState } from '@/constants/account';
@@ -25,7 +24,6 @@ import { getLocalStorage } from '@/lib/localStorage';
export type AccountState = {
balances?: Record<string, AccountBalance>;
stakingBalances?: Record<string, AccountBalance>;
tradingRewards?: TradingRewards;
wallet?: Nullable<Wallet>;
walletType?: WalletType;
@@ -181,9 +179,6 @@ export const accountSlice = createSlice({
setStakingBalances: (state, action: PayloadAction<Record<string, AccountBalance>>) => {
state.stakingBalances = action.payload;
},
setTradingRewards: (state, action: PayloadAction<TradingRewards>) => {
state.tradingRewards = action.payload;
},
addUncommittedOrderClientId: (state, action: PayloadAction<number>) => {
state.uncommittedOrderClientIds.push(action.payload);
},
@@ -211,7 +206,6 @@ export const {
viewedOrders,
setBalances,
setStakingBalances,
setTradingRewards,
addUncommittedOrderClientId,
removeUncommittedOrderClientId,
} = accountSlice.actions;
-35
View File
@@ -1,4 +1,3 @@
import type { Nullable, kollections } from '@dydxprotocol/v4-abacus';
import { OrderSide } from '@dydxprotocol/v4-client-js';
import { createSelector } from 'reselect';
@@ -10,8 +9,6 @@ import {
AbacusOrderStatus,
AbacusPositionSide,
ORDER_SIDES,
HistoricalTradingReward,
HistoricalTradingRewardsPeriod,
} from '@/constants/abacus';
import { OnboardingState } from '@/constants/account';
@@ -352,38 +349,6 @@ export const getBalances = (state: RootState) => state.account?.balances;
* */
export const getStakingBalances = (state: RootState) => state.account?.stakingBalances;
/**
* @returns account all time trading rewards
*/
export const getTotalTradingRewards = (state: RootState) => state.account?.tradingRewards?.total;
/**
* @returns account trading rewards aggregated by period
*/
export const getHistoricalTradingRewards = (state: RootState) =>
state.account?.tradingRewards?.historical;
/**
* @returns account historical trading rewards for the specified perid
*/
export const getHistoricalTradingRewardsForPeriod = (period: string) =>
createSelector(
[getHistoricalTradingRewards],
(
historicalTradingRewards: Nullable<
kollections.Map<string, kollections.List<HistoricalTradingReward>>
>
) => historicalTradingRewards?.get(period)
);
/**
* @returns account historical trading rewards for the current week
*/
export const getHistoricalTradingRewardsForCurrentWeek = createSelector(
[getHistoricalTradingRewardsForPeriod(HistoricalTradingRewardsPeriod.WEEKLY.name)],
(historicalTradingRewards) => historicalTradingRewards?.firstOrNull()
);
/**
* @returns UsageRestriction of the current session
*/
+24 -26
View File
@@ -12,35 +12,35 @@ export enum AppTheme {
Light = 'Light',
}
export enum AppThemeSystemSetting {
System = 'System',
}
export type AppThemeSetting = AppTheme | AppThemeSystemSetting;
export enum AppColorMode {
GreenUp = 'GreenUp',
RedUp = 'RedUp',
}
export interface ConfigsState {
appThemeSetting: AppThemeSetting;
appColorMode: AppColorMode;
appTheme: AppTheme;
feeTiers?: kollections.List<FeeTier>;
feeDiscounts?: FeeDiscount[];
network?: NetworkConfigs;
hasSeenLaunchIncentives: boolean;
}
const DOCUMENT_THEME_MAP = {
[AppTheme.Classic]: () => {
document?.documentElement?.classList.remove('theme-dark', 'theme-light');
},
[AppTheme.Dark]: () => {
document?.documentElement?.classList.remove('theme-light');
document?.documentElement?.classList.add('theme-dark');
},
[AppTheme.Light]: () => {
document?.documentElement?.classList.remove('theme-dark');
document?.documentElement?.classList.add('theme-light');
},
};
export const changeTheme = (theme: AppTheme) => DOCUMENT_THEME_MAP[theme]();
const initialState: ConfigsState = {
appThemeSetting: getLocalStorage({
appTheme: getLocalStorage({
key: LocalStorageKey.SelectedTheme,
defaultValue: AppTheme.Classic,
}),
appColorMode: getLocalStorage({
key: LocalStorageKey.SelectedColorMode,
defaultValue: AppColorMode.GreenUp,
}),
feeDiscounts: undefined,
feeTiers: undefined,
network: undefined,
@@ -50,17 +50,16 @@ const initialState: ConfigsState = {
}),
};
changeTheme(initialState.appTheme);
export const configsSlice = createSlice({
name: 'Inputs',
initialState,
reducers: {
setAppThemeSetting: (state: ConfigsState, { payload }: PayloadAction<AppThemeSetting>) => {
setAppTheme: (state: ConfigsState, { payload }: PayloadAction<AppTheme>) => {
setLocalStorage({ key: LocalStorageKey.SelectedTheme, value: payload });
state.appThemeSetting = payload;
},
setAppColorMode: (state: ConfigsState, { payload }: PayloadAction<AppColorMode>) => {
setLocalStorage({ key: LocalStorageKey.SelectedColorMode, value: payload });
state.appColorMode = payload;
changeTheme(payload);
state.appTheme = payload;
},
setConfigs: (state: ConfigsState, action: PayloadAction<Nullable<Configs>>) => ({
...state,
@@ -73,5 +72,4 @@ export const configsSlice = createSlice({
},
});
export const { setAppThemeSetting, setAppColorMode, setConfigs, markLaunchIncentivesSeen } =
configsSlice.actions;
export const { setAppTheme, setConfigs, markLaunchIncentivesSeen } = configsSlice.actions;
+1 -16
View File
@@ -1,21 +1,6 @@
import type { RootState } from './_store';
import { AppTheme, AppThemeSystemSetting, AppThemeSetting } from './configs';
export const getAppThemeSetting = (state: RootState): AppThemeSetting =>
state.configs.appThemeSetting;
export const getAppTheme = (state: RootState): AppTheme => {
switch (state.configs.appThemeSetting) {
case AppThemeSystemSetting.System:
return globalThis.matchMedia('(prefers-color-scheme: dark)').matches
? AppTheme.Dark
: AppTheme.Light;
default:
return state.configs.appThemeSetting;
}
};
export const getAppColorMode = (state: RootState) => state.configs.appColorMode;
export const getAppTheme = (state: RootState) => state.configs.appTheme;
export const getFeeTiers = (state: RootState) => state.configs.feeTiers?.toArray();
+1 -1
View File
@@ -38,7 +38,7 @@ export const formMixins: Record<
border-radius: var(--input-radius);
&:focus-within {
filter: brightness(var(--hover-filter-base));
filter: brightness(1.1);
}
@media ${breakpoints.tablet} {
-8
View File
@@ -18,7 +18,6 @@ export const GlobalStyle = createGlobalStyle`
--color-text-0: ${({ theme }) => theme.textTertiary};
--color-text-1: ${({ theme }) => theme.textSecondary};
--color-text-2: ${({ theme }) => theme.textPrimary};
--color-text-button: ${({ theme }) => theme.textButton};
--color-gradient-base-0: ${({ theme }) => theme.gradientBase0};
--color-gradient-base-1: ${({ theme }) => theme.gradientBase1};
@@ -30,9 +29,6 @@ export const GlobalStyle = createGlobalStyle`
--color-success: ${({ theme }) => theme.success};
--color-warning: ${({ theme }) => theme.warning};
--color-error: ${({ theme }) => theme.error};
--color-gradient-success: ${({ theme }) => theme.successFaded};
--color-gradient-warning: ${({ theme }) => theme.warningFaded};
--color-gradient-error: ${({ theme }) => theme.errorFaded};
--color-positive: ${({ theme }) => theme.positive};
--color-negative: ${({ theme }) => theme.negative};
@@ -42,9 +38,5 @@ export const GlobalStyle = createGlobalStyle`
--color-risk-low: ${({ theme }) => theme.riskLow};
--color-risk-medium: ${({ theme }) => theme.riskMedium};
--color-risk-high: ${({ theme }) => theme.riskHigh};
--hover-filter-base: ${({ theme }) => theme.hoverFilterBase};
--hover-filter-variant: ${({ theme }) => theme.hoverFilterVariant};
--active-filter: ${({ theme }) => theme.activeFilter};
}
`;
+3 -3
View File
@@ -21,8 +21,8 @@ export const popoverMixins = {
--trigger-open-backgroundColor: var(--color-layer-1);
--trigger-open-textColor: var(--color-text-2);
--trigger-active-filter: brightness(var(--active-filter));
--trigger-hover-filter: brightness(var(--hover-filter-base));
--trigger-active-filter: brightness(0.9);
--trigger-hover-filter: brightness(1.1);
display: flex;
align-items: center;
@@ -219,7 +219,7 @@ export const popoverMixins = {
&[aria-selected="true"], // cmdk
&[data-highlighted] // @radix-ui
{
filter: brightness(var(--hover-filter-base));
filter: brightness(1.1);
background-color: var(--item-highlighted-backgroundColor);
color: var(--item-highlighted-textColor, var(--trigger-textColor, inherit)) !important;
outline: none;
+9 -47
View File
@@ -1,9 +1,9 @@
import { AppTheme, AppColorMode } from '@/state/configs';
import type { Theme, ThemeColorBase } from '@/constants/styles/colors';
import { BrightnessFilterToken, ColorToken, OpacityToken } from '@/constants/styles/base';
import { AppTheme } from '@/state/configs';
import type { ThemeColors } from '@/constants/styles/colors';
import { ColorToken, OpacityToken } from '@/constants/styles/base';
import { generateFadedColorVariant } from '@/lib/styles';
const ClassicThemeBase: ThemeColorBase = {
const ClassicTheme: ThemeColors = {
layer0: ColorToken.GrayBlue7,
layer1: ColorToken.GrayBlue6,
layer2: ColorToken.GrayBlue5,
@@ -20,7 +20,6 @@ const ClassicThemeBase: ThemeColorBase = {
textPrimary: ColorToken.LightGray2,
textSecondary: ColorToken.GrayPurple1,
textTertiary: ColorToken.GrayPurple2,
textButton: ColorToken.LightGray2,
gradientBase0: ColorToken.DarkGray9,
gradientBase1: ColorToken.GrayBlue2,
@@ -32,9 +31,6 @@ const ClassicThemeBase: ThemeColorBase = {
success: ColorToken.Green1,
warning: ColorToken.Yellow0,
error: ColorToken.Red2,
successFaded: generateFadedColorVariant(ColorToken.Green1, OpacityToken.Opacity16),
warningFaded: generateFadedColorVariant(ColorToken.Yellow0, OpacityToken.Opacity16),
errorFaded: generateFadedColorVariant(ColorToken.Red2, OpacityToken.Opacity16),
positive: ColorToken.Green1,
negative: ColorToken.Red2,
@@ -54,13 +50,9 @@ const ClassicThemeBase: ThemeColorBase = {
switchThumbActiveBackground: ColorToken.White,
toggleBackground: ColorToken.GrayBlue3,
tooltipBackground: generateFadedColorVariant(ColorToken.GrayBlue3, OpacityToken.Opacity66),
hoverFilterBase: BrightnessFilterToken.Lighten10,
hoverFilterVariant: BrightnessFilterToken.Lighten10,
activeFilter: BrightnessFilterToken.Darken10,
};
const DarkThemeBase: ThemeColorBase = {
const DarkTheme: ThemeColors = {
layer0: ColorToken.Black,
layer1: ColorToken.DarkGray11,
layer2: ColorToken.DarkGray13,
@@ -77,7 +69,6 @@ const DarkThemeBase: ThemeColorBase = {
textPrimary: ColorToken.LightGray0,
textSecondary: ColorToken.MediumGray0,
textTertiary: ColorToken.DarkGray0,
textButton: ColorToken.LightGray0,
gradientBase0: ColorToken.DarkGray8,
gradientBase1: ColorToken.DarkGray5,
@@ -89,9 +80,6 @@ const DarkThemeBase: ThemeColorBase = {
success: ColorToken.Green0,
warning: ColorToken.Yellow0,
error: ColorToken.Red0,
successFaded: generateFadedColorVariant(ColorToken.Green0, OpacityToken.Opacity16),
warningFaded: generateFadedColorVariant(ColorToken.Yellow0, OpacityToken.Opacity16),
errorFaded: generateFadedColorVariant(ColorToken.Red0, OpacityToken.Opacity16),
positive: ColorToken.Green0,
negative: ColorToken.Red0,
@@ -111,13 +99,9 @@ const DarkThemeBase: ThemeColorBase = {
switchThumbActiveBackground: ColorToken.White,
toggleBackground: ColorToken.DarkGray6,
tooltipBackground: generateFadedColorVariant(ColorToken.DarkGray6, OpacityToken.Opacity66),
hoverFilterBase: BrightnessFilterToken.Lighten10,
hoverFilterVariant: BrightnessFilterToken.Lighten10,
activeFilter: BrightnessFilterToken.Darken10,
};
const LightThemeBase: ThemeColorBase = {
const LightTheme: ThemeColors = {
layer0: ColorToken.White,
layer1: ColorToken.LightGray6,
layer2: ColorToken.White,
@@ -134,7 +118,6 @@ const LightThemeBase: ThemeColorBase = {
textPrimary: ColorToken.DarkGray12,
textSecondary: ColorToken.DarkGray3,
textTertiary: ColorToken.DarkGray1,
textButton: ColorToken.White,
gradientBase0: ColorToken.LightGray8,
gradientBase1: ColorToken.LightGray5,
@@ -146,9 +129,6 @@ const LightThemeBase: ThemeColorBase = {
success: ColorToken.Green2,
warning: ColorToken.Yellow0,
error: ColorToken.Red1,
successFaded: generateFadedColorVariant(ColorToken.Green2, OpacityToken.Opacity16),
warningFaded: generateFadedColorVariant(ColorToken.Yellow0, OpacityToken.Opacity16),
errorFaded: generateFadedColorVariant(ColorToken.Red1, OpacityToken.Opacity16),
positive: ColorToken.Green2,
negative: ColorToken.Red1,
@@ -168,28 +148,10 @@ const LightThemeBase: ThemeColorBase = {
switchThumbActiveBackground: ColorToken.White,
toggleBackground: ColorToken.LightGray4,
tooltipBackground: generateFadedColorVariant(ColorToken.LightGray7, OpacityToken.Opacity66),
hoverFilterBase: BrightnessFilterToken.Darken5,
hoverFilterVariant: BrightnessFilterToken.Lighten10,
activeFilter: BrightnessFilterToken.Darken10,
};
const generateTheme = (themeBase: ThemeColorBase): Theme => {
return {
[AppColorMode.GreenUp]: themeBase,
[AppColorMode.RedUp]: {
...themeBase,
// #InvertDirectionalColors
positive: themeBase.negative,
negative: themeBase.positive,
positiveFaded: themeBase.negativeFaded,
negativeFaded: themeBase.positiveFaded,
},
};
};
export const Themes = {
[AppTheme.Classic]: generateTheme(ClassicThemeBase),
[AppTheme.Dark]: generateTheme(DarkThemeBase),
[AppTheme.Light]: generateTheme(LightThemeBase),
[AppTheme.Classic]: ClassicTheme,
[AppTheme.Dark]: DarkTheme,
[AppTheme.Light]: LightTheme,
};
@@ -231,7 +231,7 @@ Styled.CircleContainer = styled.div`
`;
Styled.Icon = styled(Icon)`
color: var(--color-error);
color: var(--color-negative);
`;
Styled.WithUsage = styled.div`
+14 -19
View File
@@ -3,26 +3,23 @@ import { useNavigate } from 'react-router-dom';
import styled, { type AnyStyledComponent, css, keyframes } from 'styled-components';
import { useSelector } from 'react-redux';
import { ButtonSize } from '@/constants/buttons';
import { STRING_KEYS } from '@/constants/localization';
import { MarketFilters, type MarketData } from '@/constants/markets';
import { AppRoute, MarketsRoute } from '@/constants/routes';
import { useStringGetter } from '@/hooks';
import { useMarketsData } from '@/hooks/useMarketsData';
import { usePotentialMarkets } from '@/hooks/usePotentialMarkets';
import { AppRoute } from '@/constants/routes';
import { useStringGetter } from '@/hooks';
import { popoverMixins } from '@/styles/popoverMixins';
import { layoutMixins } from '@/styles/layoutMixins';
import { AssetIcon } from '@/components/AssetIcon';
import { Button } from '@/components/Button';
import { Icon, IconName } from '@/components/Icon';
import { Output, OutputType } from '@/components/Output';
import { Popover, TriggerType } from '@/components/Popover';
import { ColumnDef, Table } from '@/components/Table';
import { Tag } from '@/components/Tag';
import { Toolbar } from '@/components/Toolbar';
import { ColumnDef, Table } from '@/components/Table';
import { useMarketsData } from '@/hooks/useMarketsData';
import { getSelectedLocale } from '@/state/localizationSelectors';
import { MustBigNumber } from '@/lib/numbers';
@@ -35,8 +32,6 @@ const MarketsDropdownContent = ({ onRowAction }: { onRowAction?: (market: string
const selectedLocale = useSelector(getSelectedLocale);
const [searchFilter, setSearchFilter] = useState<string>();
const { filteredMarkets, marketFilters } = useMarketsData(filter, searchFilter);
const navigate = useNavigate();
const { hasPotentialMarketsData } = usePotentialMarkets();
return (
<>
@@ -139,16 +134,16 @@ const MarketsDropdownContent = ({ onRowAction }: { onRowAction?: (market: string
})}
</h2>
<p>{stringGetter({ key: STRING_KEYS.MARKET_SEARCH_DOES_NOT_EXIST_YET })}</p>
{hasPotentialMarketsData && (
<div>
<Button
onClick={() => navigate(`${AppRoute.Markets}/${MarketsRoute.New}`)}
size={ButtonSize.Small}
>
{stringGetter({ key: STRING_KEYS.PROPOSE_NEW_MARKET })}
</Button>
</div>
)}
{/* TODO TRCL-1693 - uncomment when feedback modal is finalized
<div>
<Button
// TODO: uncomment when feedback modal is finalized
// onClick={() => dispatch(openModal({ modalType: MODALS.FEEDBACK }))}
size={ButtonSize.Small}
>
{stringGetter({ key: STRING_KEYS.GIVE_FEEDBACK })}
</Button>
</div> */}
</Styled.MarketNotFound>
}
/>
+3 -3
View File
@@ -557,11 +557,11 @@ Styled.PositionTile = styled(PositionTile)``;
Styled.ClosePositionButton = styled(Button)`
--button-border: solid var(--border-width) var(--color-border-red);
--button-textColor: var(--color-error);
--button-textColor: var(--color-negative);
`;
Styled.ClosePositionToggleButton = styled(ToggleButton)`
--button-border: solid var(--border-width) var(--color-border-red);
--button-toggle-off-textColor: var(--color-error);
--button-toggle-on-textColor: var(--color-error);
--button-toggle-off-textColor: var(--color-negative);
--button-toggle-on-textColor: var(--color-negative);
`;
+124 -13
View File
@@ -9,30 +9,34 @@ import {
HistoricalPnlPeriods,
HISTORICAL_PNL_PERIODS,
} from '@/constants/abacus';
// import { STRING_KEYS } from '@/constants/localization';
import { timeUnits } from '@/constants/time';
import { breakpoints } from '@/styles';
import { useBreakpoints, useNow } from '@/hooks';
import { useBreakpoints, useNow /*, useStringGetter*/ } from '@/hooks';
import { Output } from '@/components/Output';
// import { Details } from '@/components/Details';
import { Output /*, OutputType, ShowSign*/ } from '@/components/Output';
// import { HorizontalSeparator } from '@/components/Separator';
import { ToggleGroup } from '@/components/ToggleGroup';
import type { TooltipContextType } from '@visx/xychart';
import { TimeSeriesChart } from '@/components/visx/TimeSeriesChart';
import { AxisLabelOutput } from '@/components/visx/AxisLabelOutput';
// import { TooltipContent } from '@/components/visx/TooltipContent';
import {
getSubaccount,
getSubaccountHistoricalPnl,
getSubaccountId,
} from '@/state/accountSelectors';
import { AppTheme } from '@/state/configs';
import { getAppTheme } from '@/state/configsSelectors';
import abacusStateManager from '@/lib/abacus';
import { formatRelativeTime } from '@/lib/dateTime';
import { isTruthy } from '@/lib/isTruthy';
import chartBackground from '/chart-background.png';
enum PnlSide {
Profit = 'Profit',
Loss = 'Loss',
@@ -58,9 +62,6 @@ const MS_FOR_PERIOD = {
[HistoricalPnlPeriod.Period90d.name]: 90 * timeUnits.day,
};
const DARK_CHART_BACKGROUND_URL = '/chart-dots-background-dark.svg';
const LIGHT_CHART_BACKGROUND_URL = '/chart-dots-background-light.svg';
type ElementProps = {
onTooltipContext?: (tooltipContext: TooltipContextType<PnlDatum>) => void;
onVisibleDataChange?: (data: Array<PnlDatum>) => void;
@@ -81,8 +82,8 @@ export const PnlChart = ({
selectedLocale,
slotEmpty,
}: PnlChartProps) => {
// const stringGetter = useStringGetter();
const { isTablet } = useBreakpoints();
const appTheme = useSelector(getAppTheme);
const { equity } = useSelector(getSubaccount, shallowEqual) || {};
const now = useNow({ intervalMs: timeUnits.minute });
@@ -170,11 +171,10 @@ export const PnlChart = ({
[pnlData, equity, selectedPeriod, now]
);
const chartBackground =
appTheme === AppTheme.Light ? LIGHT_CHART_BACKGROUND_URL : DARK_CHART_BACKGROUND_URL;
// const latestDatum = data?.[data.length - 1];
return (
<Styled.Container className={className} chartBackground={chartBackground}>
<Styled.Container className={className}>
<TimeSeriesChart
id="pnl-chart"
selectedLocale={selectedLocale}
@@ -198,6 +198,25 @@ export const PnlChart = ({
yAccessor: (datum) => datum?.equity,
colorAccessor: () => 'var(--pnl-line-color)',
getCurve: () => curveLinear,
// getCurve: ({ zoomDomain }) =>
// PNL_TIME_RESOLUTION * 30 < zoomDomain && zoomDomain < PNL_TIME_RESOLUTION * 400
// ? curveMonotoneX
// : curveLinear,
// threshold: {
// yAccessor: (datum) => datum?.netTransfers,
// aboveAreaProps: {
// fill: 'var(--color-positive)',
// fillOpacity: 0.33,
// strokeWidth: 1,
// stroke: 'var(--color-positive)',
// },
// belowAreaProps: {
// fill: 'var(--color-negative)',
// fillOpacity: 0.33,
// strokeWidth: 1,
// stroke: 'var(--color-negative)',
// },
// },
},
]}
tickFormatY={(value) =>
@@ -210,6 +229,98 @@ export const PnlChart = ({
.format(Math.abs(value))
.toLowerCase()
}
// renderXAxisLabel={({ tooltipData }) => {
// const tooltipDatum = tooltipData!.nearestDatum!.datum ?? latestDatum;
// return (
// <Styled.XAxisLabelOutput type={OutputType.DateTime} value={tooltipDatum.createdAt} />
// );
// }}
// renderYAxisLabel={({ tooltipData }) => {
// const tooltipDatum = tooltipData!.nearestDatum!.datum ?? latestDatum;
// return (
// <Styled.YAxisLabelOutput
// type={OutputType.CompactFiat}
// value={tooltipDatum.totalPnl}
// accentColor={
// {
// [PnlSide.Loss]: 'var(--color-negative)',
// [PnlSide.Profit]: 'var(--color-positive)',
// [PnlSide.Flat]: 'var(--color-layer-6)',
// }[tooltipDatum.side]
// }
// />
// );
// }}
// renderTooltip={({ tooltipData }) => {
// const { nearestDatum } = tooltipData || {};
// const tooltipDatum = nearestDatum?.datum ?? latestDatum;
// return (
// <TooltipContent
// accentColor={
// {
// [PnlSide.Loss]: 'var(--color-negative)',
// [PnlSide.Profit]: 'var(--color-positive)',
// [PnlSide.Flat]: 'var(--color-layer-6)',
// }[tooltipDatum.side]
// }
// >
// <Details
// layout="column"
// items={[
// {
// key: 'createdAt',
// label: stringGetter({ key: STRING_KEYS.TIME }),
// value: <Output type={OutputType.DateTime} value={tooltipDatum.createdAt} />,
// },
// ].filter(Boolean)}
// />
// <HorizontalSeparator />
// <Details
// layout="column"
// items={[
// {
// key: 'netTransfers',
// label: stringGetter({ key: STRING_KEYS.NET_TRANSFERS }),
// value: <Output type={OutputType.Fiat} value={tooltipDatum.netTransfers} />,
// },
// {
// key: 'equity',
// label: {
// [PnlSide.Profit]: stringGetter({
// key: STRING_KEYS.NET_PROFIT,
// }),
// [PnlSide.Loss]: stringGetter({
// key: STRING_KEYS.NET_LOSS,
// }),
// [PnlSide.Flat]: stringGetter({
// key: STRING_KEYS.NET_ZERO,
// }),
// }[tooltipDatum.side],
// value: (
// <Styled.SignedOutput
// type={OutputType.Fiat}
// value={tooltipDatum.equity}
// showSign={ShowSign.Both}
// side={tooltipDatum.side}
// />
// ),
// },
// {
// key: 'totalPnl',
// label: stringGetter({ key: STRING_KEYS.TOTAL_VALUE }), // stringGetter({ key: STRING_KEYS.EQUITY }),
// value: <Output type={OutputType.Fiat} value={tooltipDatum.totalPnl} />,
// },
// ].filter(Boolean)}
// />
// </TooltipContent>
// );
// }}
renderTooltip={() => <div />}
onTooltipContext={onTooltipContext}
onVisibleDataChange={onVisibleDataChange}
@@ -247,9 +358,9 @@ export const PnlChart = ({
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Container = styled.div<{ chartBackground: string }>`
Styled.Container = styled.div`
position: relative;
background: url(${({ chartBackground }) => chartBackground}) no-repeat center center;
background: url(${chartBackground}) no-repeat center center;
`;
Styled.PeriodToggle = styled.div`
-349
View File
@@ -1,349 +0,0 @@
import { useDispatch, useSelector } from 'react-redux';
import styled, { AnyStyledComponent, css } from 'styled-components';
import { Root, Item, Indicator } from '@radix-ui/react-radio-group';
import { useStringGetter } from '@/hooks';
import {
AppTheme,
type AppThemeSetting,
AppThemeSystemSetting,
AppColorMode,
setAppThemeSetting,
setAppColorMode,
} from '@/state/configs';
import { getAppTheme, getAppThemeSetting, getAppColorMode } from '@/state/configsSelectors';
import { layoutMixins } from '@/styles/layoutMixins';
import { Themes } from '@/styles/themes';
import { STRING_KEYS } from '@/constants/localization';
import { Dialog } from '@/components/Dialog';
import { Icon, IconName } from '@/components/Icon';
import { HorizontalSeparatorFiller } from '@/components/Separator';
type ElementProps = {
setIsOpen: (open: boolean) => void;
};
export const DisplaySettingsDialog = ({ setIsOpen }: ElementProps) => {
const dispatch = useDispatch();
const stringGetter = useStringGetter();
const currentThemeSetting: AppThemeSetting = useSelector(getAppThemeSetting);
const currentTheme: AppTheme = useSelector(getAppTheme);
const currentColorMode: AppColorMode = useSelector(getAppColorMode);
const sectionHeader = (heading: string) => {
return (
<Styled.Header>
{heading}
{heading}
<HorizontalSeparatorFiller />
</Styled.Header>
);
};
const themePanels = () => {
return (
<Styled.AppThemeRoot value={currentThemeSetting}>
{[
{
themeSetting: AppTheme.Classic,
label: STRING_KEYS.CLASSIC_DARK,
},
{
themeSetting: AppThemeSystemSetting.System,
label: STRING_KEYS.SYSTEM,
},
{
themeSetting: AppTheme.Dark,
label: STRING_KEYS.DARK,
},
{
themeSetting: AppTheme.Light,
label: STRING_KEYS.LIGHT,
},
].map(({ themeSetting, label }) => {
const theme =
themeSetting === AppThemeSystemSetting.System
? globalThis.matchMedia('(prefers-color-scheme: dark)').matches
? AppTheme.Dark
: AppTheme.Light
: themeSetting;
const backgroundColor = Themes[theme][currentColorMode].layer2;
const gridColor = Themes[theme][currentColorMode].borderDefault;
const textColor = Themes[theme][currentColorMode].textPrimary;
return (
<Styled.AppThemeItem
key={themeSetting}
value={themeSetting}
backgroundcolor={backgroundColor}
gridcolor={gridColor}
onClick={() => {
dispatch(setAppThemeSetting(themeSetting));
}}
>
<Styled.AppThemeHeader textcolor={textColor}>
{stringGetter({ key: label })}
</Styled.AppThemeHeader>
<Styled.Image src="/chart-bars.svg" />
<Styled.CheckIndicator>
<Styled.CheckIcon iconName={IconName.Check} />
</Styled.CheckIndicator>
</Styled.AppThemeItem>
);
})}
</Styled.AppThemeRoot>
);
};
const colorModeOptions = () => {
return (
<Styled.ColorPreferenceRoot value={currentColorMode}>
{[
{
colorMode: AppColorMode.GreenUp,
label: STRING_KEYS.GREEN_IS_UP,
},
{
colorMode: AppColorMode.RedUp,
label: STRING_KEYS.RED_IS_UP,
},
].map(({ colorMode, label }) => (
<Styled.ColorPreferenceItem
key={colorMode}
value={colorMode}
onClick={() => {
dispatch(setAppColorMode(colorMode));
}}
>
<Styled.ColorPreferenceLabel>
<Styled.ArrowIconContainer>
<Styled.ArrowIcon
iconName={IconName.Arrow}
direction="up"
color={colorMode === AppColorMode.GreenUp ? 'green' : 'red'}
/>
<Styled.ArrowIcon
iconName={IconName.Arrow}
direction="down"
color={colorMode === AppColorMode.GreenUp ? 'red' : 'green'}
/>
</Styled.ArrowIconContainer>
{stringGetter({ key: label })}
</Styled.ColorPreferenceLabel>
<Styled.DotIndicator $selected={currentColorMode === colorMode} />
</Styled.ColorPreferenceItem>
))}
</Styled.ColorPreferenceRoot>
);
};
return (
<Dialog
isOpen
setIsOpen={setIsOpen}
title={stringGetter({ key: STRING_KEYS.DISPLAY_SETTINGS })}
>
<Styled.Section>
{sectionHeader(stringGetter({ key: STRING_KEYS.THEME }))}
{themePanels()}
</Styled.Section>
<Styled.Section>
{sectionHeader(stringGetter({ key: STRING_KEYS.DIRECTION_COLOR_PREFERENCE }))}
{colorModeOptions()}
</Styled.Section>
</Dialog>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
const gridStyle = css`
display: grid;
gap: 1.5rem;
`;
Styled.Section = styled.div`
${gridStyle}
padding: 1rem 0;
`;
Styled.Header = styled.header`
${layoutMixins.inlineRow}
`;
Styled.AppThemeRoot = styled(Root)`
${gridStyle}
grid-template-columns: 1fr 1fr;
`;
Styled.ColorPreferenceRoot = styled(Root)`
${gridStyle}
grid-template-columns: 1fr;
`;
Styled.Item = styled(Item)`
--border-color: var(--color-border);
--item-padding: 0.75rem;
&[data-state='checked'] {
--border-color: var(--color-accent);
}
border: solid var(--border-width) var(--border-color);
border-radius: 0.875rem;
padding: var(--item-padding);
`;
Styled.ColorPreferenceItem = styled(Styled.Item)`
&[data-state='checked'] {
background-color: var(--color-layer-4);
}
${layoutMixins.row}
justify-content: space-between;
`;
Styled.AppThemeItem = styled(Styled.Item)<{ backgroundcolor: string; gridcolor: string }>`
${({ backgroundcolor, gridcolor }) => css`
--themePanel-backgroundColor: ${backgroundcolor};
--themePanel-gridColor: ${gridcolor};
`}
display: flex;
flex-direction: column;
position: relative;
width: 100%;
background-color: var(--themePanel-backgroundColor);
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
border-radius: 0.875rem;
background: radial-gradient(
55% 35% at 50% 65%,
transparent,
var(--themePanel-backgroundColor) 100%
);
background-color: var(--themePanel-gridColor);
mask-image: url('/chart-bars-background.svg');
mask-size: cover;
}
`;
Styled.AppThemeHeader = styled.h3<{ textcolor: string }>`
${({ textcolor }) => css`
color: ${textcolor};
`}
z-index: 1;
`;
Styled.Image = styled.img`
width: 100%;
height: auto;
z-index: 1;
`;
Styled.ColorPreferenceLabel = styled.div`
${layoutMixins.inlineRow};
gap: 1ch;
`;
Styled.ArrowIconContainer = styled.div`
${layoutMixins.column}
gap: 0.5ch;
svg {
height: 0.75em;
width: 0.75em;
}
`;
Styled.ArrowIcon = styled(Icon)<{ direction: 'up' | 'down'; color: 'green' | 'red' }>`
${({ direction }) =>
({
['up']: css`
transform: rotate(-90deg);
`,
['down']: css`
transform: rotate(90deg);
`,
}[direction])}
${({ color }) =>
({
['green']: css`
color: var(--color-success);
`,
['red']: css`
color: var(--color-error);
`,
}[color])}
`;
const indicatorStyle = css`
--indicator-size: 1.25rem;
--icon-size: 0.5rem;
height: var(--indicator-size);
width: var(--indicator-size);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
`;
Styled.DotIndicator = styled.div<{ $selected: boolean }>`
${indicatorStyle}
--background-color: var(--color-layer-2);
--border-color: var(--color-border);
${({ $selected }) =>
$selected &&
css`
--background-color: var(--color-accent);
--border-color: var(--color-accent);
&::after {
content: '';
display: block;
width: var(--icon-size);
height: var(--icon-size);
background-color: var(--color-layer-2);
border-radius: 50%;
}
`}
background-color: var(--background-color);
border: solid var(--border-width) var(--border-color);
`;
Styled.CheckIndicator = styled(Indicator)`
${indicatorStyle}
position: absolute;
bottom: var(--item-padding);
right: var(--item-padding);
background-color: var(--color-accent);
color: var(--color-text-button);
`;
Styled.CheckIcon = styled(Icon)`
width: var(--icon-size);
height: var(--icon-size);
`;
+1 -1
View File
@@ -189,7 +189,7 @@ Styled.WordList = styled.div<{ isShowing?: boolean }>`
padding: 1rem;
&:hover {
filter: brightness(var(--hover-filter-base));
filter: brightness(1.1);
}
> :first-child {
+1 -1
View File
@@ -183,7 +183,7 @@ Styled.QrCodeContainer = styled.figure<{ isShowing: boolean }>`
transition: 0.2s;
&:hover {
filter: brightness(var(--hover-filter-base));
filter: brightness(1.1);
}
> * {
@@ -1,105 +0,0 @@
import { useState } from 'react';
import styled, { AnyStyledComponent } from 'styled-components';
import { ButtonAction } from '@/constants/buttons';
import { AppRoute } from '@/constants/routes';
import { STRING_KEYS } from '@/constants/localization';
import { useStringGetter } from '@/hooks';
import breakpoints from '@/styles/breakpoints';
import { layoutMixins } from '@/styles/layoutMixins';
import { Button } from '@/components/Button';
import { Checkbox } from '@/components/Checkbox';
import { Dialog } from '@/components/Dialog';
import { Link } from '@/components/Link';
type ElementProps = {
acceptTerms: () => void;
setIsOpen: (open: boolean) => void;
};
export const NewMarketAgreementDialog = ({ acceptTerms, setIsOpen }: ElementProps) => {
const [hasAcknowledged, setHasAcknowledged] = useState(false);
const stringGetter = useStringGetter();
return (
<Styled.Dialog
isOpen
setIsOpen={setIsOpen}
title={stringGetter({ key: STRING_KEYS.ACKNOWLEDGEMENT })}
>
<Styled.Content>
<p>
{stringGetter({
key: STRING_KEYS.NEW_MARKET_PROPOSAL_AGREEMENT,
params: {
DOCUMENTATION_LINK: (
<Styled.Link href="https://docs.dydx.community/dydx-governance/voting-and-governance/governance-process">
{stringGetter({ key: STRING_KEYS.WEBSITE }).toLowerCase()}
</Styled.Link>
),
TERMS_OF_USE: (
<Styled.Link href={`/#${AppRoute.Terms}`}>
{stringGetter({ key: STRING_KEYS.TERMS_OF_USE })}
</Styled.Link>
),
},
})}
</p>
<Checkbox
checked={hasAcknowledged}
onCheckedChange={setHasAcknowledged}
id="acknowledgement-checkbox"
label={stringGetter({ key: STRING_KEYS.I_HAVE_READ_AND_AGREE })}
/>
<Styled.ButtonRow>
<Button action={ButtonAction.Base} onClick={() => setIsOpen(false)}>
{stringGetter({ key: STRING_KEYS.CANCEL })}
</Button>
<Button
action={ButtonAction.Primary}
onClick={() => {
acceptTerms();
setIsOpen(false);
}}
state={{ isDisabled: !hasAcknowledged }}
>
{stringGetter({ key: STRING_KEYS.CONTINUE })}
</Button>
</Styled.ButtonRow>
</Styled.Content>
</Styled.Dialog>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Dialog = styled(Dialog)`
@media ${breakpoints.notMobile} {
--dialog-width: 30rem;
}
`;
Styled.Content = styled.div`
${layoutMixins.column}
gap: 1rem;
p {
border-radius: 0.5rem;
padding: 1rem;
background-color: var(--color-layer-1);
}
`;
Styled.Link = styled(Link)`
--link-color: var(--color-accent);
display: inline-block;
`;
Styled.ButtonRow = styled.div`
display: grid;
grid-template-columns: 1fr 2fr;
gap: 1rem;
`;
@@ -1,366 +0,0 @@
import { useMemo, useState } from 'react';
import styled, { AnyStyledComponent } from 'styled-components';
import { utils } from '@dydxprotocol/v4-client-js';
import { STRING_KEYS } from '@/constants/localization';
import { isMainnet } from '@/constants/networks';
import { PotentialMarketItem } from '@/constants/potentialMarkets';
import { useGovernanceVariables, useStringGetter, useTokenConfigs } from '@/hooks';
import { usePotentialMarkets } from '@/hooks/usePotentialMarkets';
import { layoutMixins } from '@/styles/layoutMixins';
import { Details } from '@/components/Details';
import { Dialog } from '@/components/Dialog';
import { Output, OutputType } from '@/components/Output';
import { Tag, TagType } from '@/components/Tag';
import { ToggleGroup } from '@/components/ToggleGroup';
import { MustBigNumber } from '@/lib/numbers';
type ElementProps = {
preventClose?: boolean;
setIsOpen?: (open: boolean) => void;
assetData?: PotentialMarketItem;
clobPairId?: number;
liquidityTier?: string;
};
export enum CodeToggleGroup {
CREATE_ORACLE = 'CREATE_ORACLE',
MSG_CREATE_PERPETUAL = 'MSG_CREATE_PERPETUAL',
MSG_CREATE_CLOB_PAIR = 'MSG_CREATE_CLOB_PAIR',
MSG_DELAY_MESSAGE = 'MSG_DELAY_MESSAGE',
MSG_SUBMIT_PROPOSAL = 'MSG_SUBMIT_PROPOSAL',
}
export const NewMarketMessageDetailsDialog = ({
assetData,
clobPairId,
liquidityTier,
preventClose,
setIsOpen,
}: ElementProps) => {
const [codeToggleGroup, setCodeToggleGroup] = useState(CodeToggleGroup.CREATE_ORACLE);
const { exchangeConfigs } = usePotentialMarkets();
const { baseAsset } = assetData ?? {};
const { newMarketProposal } = useGovernanceVariables();
const stringGetter = useStringGetter();
const { chainTokenDecimals, chainTokenLabel } = useTokenConfigs();
const initialDepositAmountDecimals = isMainnet ? 0 : chainTokenDecimals;
const exchangeConfig = useMemo(() => {
return baseAsset ? exchangeConfigs?.[baseAsset] : undefined;
}, [baseAsset]);
const ticker = useMemo(() => `${baseAsset}-USD`, [baseAsset]);
const toggleGroupItems: Parameters<typeof ToggleGroup>[0]['items'] = useMemo(() => {
return [
{
value: CodeToggleGroup.CREATE_ORACLE,
label: 'Create oracle market',
},
{
value: CodeToggleGroup.MSG_CREATE_PERPETUAL,
label: 'Msg create perpetual',
},
{
value: CodeToggleGroup.MSG_CREATE_CLOB_PAIR,
label: 'Msg create clobPair',
},
{
value: CodeToggleGroup.MSG_DELAY_MESSAGE,
label: 'Msg delay message',
},
{
value: CodeToggleGroup.MSG_SUBMIT_PROPOSAL,
label: 'Msg submit proposal',
},
];
}, []);
return (
<Dialog
isOpen
preventClose={preventClose}
setIsOpen={setIsOpen}
title={stringGetter({ key: STRING_KEYS.MESSAGE_DETAILS })}
>
<Styled.ProposedMessageDetails>
<Styled.Tabs
items={toggleGroupItems}
value={codeToggleGroup}
onValueChange={setCodeToggleGroup}
/>
{
{
[CodeToggleGroup.CREATE_ORACLE]: (
<Styled.Code>
<Styled.Details
layout="column"
items={[
{
key: 'id',
label: 'market_id',
value: `${clobPairId}`,
},
{
key: 'pair',
label: 'pair',
value: ticker,
},
{
key: 'min-exchanges',
label: 'min_exchanges',
value: `${assetData?.minExchanges}`,
},
{
key: 'min-price-change-ppm',
label: 'min_price_change_ppm',
value: `${assetData?.minPriceChangePpm}`,
},
]}
/>
<Styled.Text0>
exchange_config_json{' '}
{exchangeConfig && <Tag type={TagType.Number}>{exchangeConfig.length}</Tag>}
</Styled.Text0>
{'['}
{exchangeConfig?.map((exchange) => {
return (
<Styled.ExchangeObject
key={exchange.exchangeName}
style={{ padding: 0, margin: 0, paddingLeft: '0.5rem' }}
>
{'{'}
{Object.keys(exchange).map((key) => (
<Styled.Line key={key}>
{key}: <span>{exchange[key as keyof typeof exchange]}</span>
</Styled.Line>
))}
{'},'}
</Styled.ExchangeObject>
);
})}
{']'}
</Styled.Code>
),
[CodeToggleGroup.MSG_CREATE_PERPETUAL]: (
<Styled.Code>
<Styled.Details
layout="column"
items={[
{
key: 'perpetual_id',
label: 'perpetual_id',
value: `${clobPairId}`,
},
{
key: 'market_id',
label: 'market_id',
value: `${clobPairId}`,
},
{
key: 'ticker',
label: 'ticker',
value: ticker,
},
{
key: 'atomic_resolution',
label: 'atomic_resolution',
value: `${assetData?.atomicResolution}`,
},
{
key: 'default_funding_ppm',
label: 'default_funding_ppm',
value: '0',
},
{
key: 'liquidity_tier',
label: 'liquidity_tier',
value: liquidityTier,
},
]}
/>
</Styled.Code>
),
[CodeToggleGroup.MSG_CREATE_CLOB_PAIR]: (
<Styled.Code>
<Styled.Details
layout="column"
items={[
{
key: 'clob_id',
label: 'clob_id',
value: `${clobPairId}`,
},
{
key: 'perpetual_id',
label: 'perpetual_id',
value: `${clobPairId}`,
},
{
key: 'quantum_conversion_exponent',
label: 'quantum_conversion_exponent',
value: `${assetData?.quantumConversionExponent}`,
},
{
key: 'step_base_quantums',
label: 'step_base_quantums',
value: `${assetData?.stepBaseQuantum}`,
},
{
key: 'subticks_per_tick',
label: 'subticks_per_tick',
value: `${assetData?.subticksPerTick}`,
},
{
key: 'status',
label: 'status',
value: 'INITIALIZING',
},
]}
/>
</Styled.Code>
),
[CodeToggleGroup.MSG_DELAY_MESSAGE]: (
<Styled.Code>
<Styled.Details
layout="column"
items={[
{
key: 'delay_blocks',
label: 'delay_blocks',
value: (
<Output
type={OutputType.Asset}
value={newMarketProposal.delayBlocks}
fractionDigits={0}
/>
),
},
]}
/>
<div style={{ marginTop: '1rem' }}>MSG_UPDATE_CLOB_PAIR</div>
<Styled.Details
layout="column"
items={[
{
key: 'clob_id',
label: 'clob_id',
value: `${clobPairId}`,
},
{
key: 'perpetual_id',
label: 'perpetual_id',
value: `${clobPairId}`,
},
{
key: 'quantum_conversion_exponent',
label: 'quantum_conversion_exponent',
value: `${assetData?.quantumConversionExponent}`,
},
{
key: 'step_base_quantums',
label: 'step_base_quantums',
value: `${assetData?.stepBaseQuantum}`,
},
{
key: 'subticks_per_tick',
label: 'subticks_per_tick',
value: `${assetData?.subticksPerTick}`,
},
{
key: 'status',
label: 'status',
value: 'ACTIVE',
},
]}
/>
</Styled.Code>
),
[CodeToggleGroup.MSG_SUBMIT_PROPOSAL]: (
<Styled.Code>
<Styled.Text0>title: </Styled.Text0>
<Styled.Description>{utils.getGovAddNewMarketTitle(ticker)}</Styled.Description>
<Styled.Text0>initial_deposit_amount:</Styled.Text0>
<Styled.Description>
{
<Output
type={OutputType.Asset}
value={MustBigNumber(newMarketProposal.initialDepositAmount).div(
Number(`1e${chainTokenDecimals}`)
)}
fractionDigits={initialDepositAmountDecimals}
tag={chainTokenLabel}
/>
}
</Styled.Description>
<Styled.Text0>summary: </Styled.Text0>
<Styled.Description>
{utils.getGovAddNewMarketSummary(ticker, newMarketProposal.delayBlocks)}
</Styled.Description>
</Styled.Code>
),
}[codeToggleGroup]
}
</Styled.ProposedMessageDetails>
</Dialog>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Content = styled.div`
${layoutMixins.column}
gap: 0;
`;
Styled.ProposedMessageDetails = styled.div`
display: flex;
flex-direction: column;
gap: 1rem;
width: 100%;
background-color: var(--color-layer-3);
margin-top: 1rem;
border-radius: 10px;
`;
Styled.Tabs = styled(ToggleGroup)`
overflow-x: auto;
`;
Styled.Text0 = styled.span`
color: var(--color-text-0);
`;
Styled.Code = styled.div`
height: 16.25rem;
overflow: auto;
display: block;
background-color: var(--color-layer-1);
padding: 1rem;
border-radius: 10px;
font: var(--font-mini-book);
font-family: var(--fontFamily-monospace);
margin-top: 1rem;
gap: 0rem;
`;
Styled.ExchangeObject = styled.div`
padding: 1rem;
`;
Styled.Details = styled(Details)`
--details-item-height: 1.5rem;
`;
Styled.Line = styled.pre`
margin-left: 1rem;
`;
Styled.Description = styled.p`
margin-bottom: 1rem;
`;
@@ -323,7 +323,7 @@ Styled.ReceiptArea = styled.div`
`;
Styled.Green = styled.span`
color: var(--color-success);
color: var(--color-positive);
`;
Styled.GreenCheckCircle = styled(GreenCheckCircle)`

Some files were not shown because too many files have changed in this diff Show More