Compare commits
208 Commits
jj/README-
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d24a02f7b9 | ||
|
|
caaea7e475 | ||
|
|
9d3a124485 | ||
|
|
038eb08e2e | ||
|
|
e1d2a5eda4 | ||
|
|
56be9ba9cc | ||
|
|
859e7dde80 | ||
|
|
d9daf9f583 | ||
|
|
5be9d2b1b2 | ||
|
|
d2c5b7945b | ||
|
|
fc5d8538fe | ||
|
|
fdc262f59f | ||
|
|
7f947804bd | ||
|
|
6620a70a5d | ||
|
|
bff779631b | ||
|
|
b115bf33a0 | ||
|
|
b544b8202b | ||
|
|
ad6f99ffdf | ||
|
|
a7bd6a3ee8 | ||
|
|
c92f218493 | ||
|
|
b09fe9ebb1 | ||
|
|
1c28505ec0 | ||
|
|
5531e21c76 | ||
|
|
4ebeb21841 | ||
|
|
b638ec1ad6 | ||
|
|
f7a1cfc67e | ||
|
|
d66a776ad2 | ||
|
|
e3e00f4f1e | ||
|
|
9ea578b8e4 | ||
|
|
f47fda45bf | ||
|
|
a7addda930 | ||
|
|
b839cf695e | ||
|
|
c9b8f1d59b | ||
|
|
91c04956d6 | ||
|
|
3a3f817501 | ||
|
|
5fb2f278da | ||
|
|
bd788f22e8 | ||
|
|
1a41ccaf2a | ||
|
|
26b426c9e9 | ||
|
|
994ba832f6 | ||
|
|
597456a0d1 | ||
|
|
3b75e60bd2 | ||
|
|
e453977299 | ||
|
|
dbc34599a6 | ||
|
|
f762e9bfac | ||
|
|
ed3c336cc0 | ||
|
|
b4f9f03bdc | ||
|
|
44ed52d5e2 | ||
|
|
42595a3667 | ||
|
|
2fc55bbe9f | ||
|
|
97452d7785 | ||
|
|
2704baf378 | ||
|
|
453d7c545e | ||
|
|
f79c062808 | ||
|
|
7d30c80320 | ||
|
|
1c1d602bf3 | ||
|
|
23a96c1c20 | ||
|
|
d81e6b3a2c | ||
|
|
732114a8de | ||
|
|
2c220233e3 | ||
|
|
8187e3615b | ||
|
|
c5888c2d5c | ||
|
|
793b522487 | ||
|
|
13d6610492 | ||
|
|
9cbb9fc2c6 | ||
|
|
91f5b89eb6 | ||
|
|
41cc531700 | ||
|
|
5aeb01f968 | ||
|
|
c9596de9c3 | ||
|
|
cc8c724f09 | ||
|
|
ac07abea07 | ||
|
|
54e81cca80 | ||
|
|
0ed1f33808 | ||
|
|
48e67f5681 | ||
|
|
da1ac0d087 | ||
|
|
17fce5417a | ||
|
|
b86a346be3 | ||
|
|
5cecc40a1c | ||
|
|
7134fa541d | ||
|
|
cd30c9c7d9 | ||
|
|
414e38afec | ||
|
|
e93850484b | ||
|
|
521b6d6135 | ||
|
|
94772bf4dc | ||
|
|
149f21e7e0 | ||
|
|
0a3ef3a7ab | ||
|
|
fef9935883 | ||
|
|
c7a5b706e1 | ||
|
|
f304bb069a | ||
|
|
ad6aa1af49 | ||
|
|
55b2c3fb4a | ||
|
|
83bcde00eb | ||
|
|
e8024b9337 | ||
|
|
8280e512bc | ||
|
|
b2234cb969 | ||
|
|
4bcb1f64ac | ||
|
|
4a64d59546 | ||
|
|
3fc43e8a12 | ||
|
|
c24a9229a6 | ||
|
|
90329d44d0 | ||
|
|
9a02bd3f1c | ||
|
|
adba11b462 | ||
|
|
29526b927f | ||
|
|
503e089efa | ||
|
|
c3495f462c | ||
|
|
6da6eeb2a4 | ||
|
|
0cf3e81bd7 | ||
|
|
f8cf1d364b | ||
|
|
6f344c6b5d | ||
|
|
133856afca | ||
|
|
33c543daaf | ||
|
|
c77e727d2b | ||
|
|
b94538711d | ||
|
|
b83479f45c | ||
|
|
001aad3abc | ||
|
|
f8db5e1ba0 | ||
|
|
f8bec0fb3d | ||
|
|
8bf23b7e9c | ||
|
|
3f10e045f4 | ||
|
|
71d1a0321b | ||
|
|
0f16396c8d | ||
|
|
2709d79f59 | ||
|
|
ab0eec5d4f | ||
|
|
4a044da38f | ||
|
|
fbbfbc6580 | ||
|
|
2714c2b084 | ||
|
|
9979bc8a16 | ||
|
|
a958a59ea2 | ||
|
|
2bf9e66da5 | ||
|
|
2980144e40 | ||
|
|
5387fe8632 | ||
|
|
1132ea3bbd | ||
|
|
9188e08a4f | ||
|
|
941ef7f9dd | ||
|
|
b1ffa2e219 | ||
|
|
91ea68dc53 | ||
|
|
cf79528d05 | ||
|
|
ef81f9da57 | ||
|
|
60d59cd211 | ||
|
|
19d38378f3 | ||
|
|
15a64232c0 | ||
|
|
28d3be0370 | ||
|
|
90ff9ccc5a | ||
|
|
33516422e7 | ||
|
|
eb31610a38 | ||
|
|
b0e1655018 | ||
|
|
b4cc5f87ec | ||
|
|
549ae558e7 | ||
|
|
5b06110e2d | ||
|
|
e3da2ee4b1 | ||
|
|
6b38d68b09 | ||
|
|
1dedc93a56 | ||
|
|
1427b55728 | ||
|
|
20521b5b3f | ||
|
|
532df49a06 | ||
|
|
fb65db633a | ||
|
|
279ef6b4f9 | ||
|
|
0def18db07 | ||
|
|
50bd860ced | ||
|
|
818574cedb | ||
|
|
3be0429a60 | ||
|
|
b8e72246b9 | ||
|
|
99e708a984 | ||
|
|
876f620ada | ||
|
|
b9550890da | ||
|
|
3732b955f5 | ||
|
|
253bfc0eff | ||
|
|
d4bcfc0428 | ||
|
|
7dec32df5e | ||
|
|
e09d574d5b | ||
|
|
944fc6dc95 | ||
|
|
91a97a1c68 | ||
|
|
c5f736d805 | ||
|
|
3769f7078c | ||
|
|
edc9fadfee | ||
|
|
5e2d426cd1 | ||
|
|
766209baf1 | ||
|
|
906faa554d | ||
|
|
c339eeccde | ||
|
|
bd03fb73ca | ||
|
|
31825a8a52 | ||
|
|
8d5bf1a721 | ||
|
|
7f3d57b46a | ||
|
|
c292c84c2c | ||
|
|
2d37ff676b | ||
|
|
68f3552569 | ||
|
|
18b12591ca | ||
|
|
3f963ffb07 | ||
|
|
aac024fd5e | ||
|
|
4913c690ec | ||
|
|
b0db577b28 | ||
|
|
9815437a80 | ||
|
|
890a4b2c0e | ||
|
|
8d3cc76d14 | ||
|
|
c7ad4b3028 | ||
|
|
c88d5dd411 | ||
|
|
d6ab547055 | ||
|
|
2fe6c2bb3b | ||
|
|
e6858ca917 | ||
|
|
d92b49f4fa | ||
|
|
e7da21962a | ||
|
|
b479531e34 | ||
|
|
0d4c5a547a | ||
|
|
5b235ee53f | ||
|
|
18dee0586b | ||
|
|
9f1f5987ee | ||
|
|
7f531516ca | ||
|
|
3fd71558c0 |
17
.env.example
@ -3,7 +3,20 @@ VITE_BASE_URL=
|
|||||||
VITE_ALCHEMY_API_KEY=
|
VITE_ALCHEMY_API_KEY=
|
||||||
|
|
||||||
VITE_PK_ENCRYPTION_KEY=
|
VITE_PK_ENCRYPTION_KEY=
|
||||||
|
VITE_ROUTER_TYPE=
|
||||||
|
|
||||||
VITE_WALLETCONNECT2_PROJECT_ID=
|
VITE_V3_TOKEN_ADDRESS=
|
||||||
|
VITE_TOKEN_MIGRATION_URI=
|
||||||
|
|
||||||
VITE_V3_TOKEN_ADDRESS=
|
AMPLITUDE_API_KEY=
|
||||||
|
AMPLITUDE_SERVER_URL=
|
||||||
|
BUGSNAG_API_KEY=
|
||||||
|
IOS_APP_ID=
|
||||||
|
INTERCOM_APP_ID=
|
||||||
|
STATUS_PAGE_SCRIPT_URI=
|
||||||
|
|
||||||
|
SMARTBANNER_APP_NAME=
|
||||||
|
SMARTBANNER_ORG_NAME=
|
||||||
|
SMARTBANNER_ICON_URL=
|
||||||
|
SMARTBANNER_APPSTORE_URL=
|
||||||
|
SMARTBANNER_GOOGLEPLAY_URL=
|
||||||
|
|||||||
1
.github/workflows/deploy-testnet.yml
vendored
@ -39,6 +39,7 @@ jobs:
|
|||||||
pnpm run build:inject-amplitude
|
pnpm run build:inject-amplitude
|
||||||
pnpm run build:inject-bugsnag
|
pnpm run build:inject-bugsnag
|
||||||
pnpm run build:inject-statuspage
|
pnpm run build:inject-statuspage
|
||||||
|
pnpm run build:inject-smartbanner
|
||||||
sh scripts/inject-app-deeplinks.sh
|
sh scripts/inject-app-deeplinks.sh
|
||||||
|
|
||||||
- name: Upload to IPFS via web3.storage
|
- name: Upload to IPFS via web3.storage
|
||||||
|
|||||||
@ -2,74 +2,132 @@ import '@/polyfills';
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import { WagmiConfig } from 'wagmi';
|
||||||
|
import { GrazProvider } from 'graz';
|
||||||
|
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||||
|
|
||||||
import { store } from '@/state/_store';
|
import { SupportedLocales } from '@/constants/localization';
|
||||||
|
|
||||||
|
import { AccountsProvider } from '@/hooks/useAccounts';
|
||||||
|
import { AppThemeAndColorModeProvider } from '@/hooks/useAppThemeAndColorMode';
|
||||||
|
import { DydxProvider } from '@/hooks/useDydxClient';
|
||||||
|
import { DialogAreaProvider } from '@/hooks/useDialogArea';
|
||||||
|
import { LocaleProvider } from '@/hooks/useLocaleSeparators';
|
||||||
|
import { PotentialMarketsProvider } from '@/hooks/usePotentialMarkets';
|
||||||
|
import { RestrictionProvider } from '@/hooks/useRestrictions';
|
||||||
|
import { SubaccountProvider } from '@/hooks/useSubaccount';
|
||||||
|
|
||||||
|
import { GlobalStyle } from '@/styles/globalStyle';
|
||||||
|
|
||||||
import { SelectMenu, SelectItem } from '@/components/SelectMenu';
|
import { SelectMenu, SelectItem } from '@/components/SelectMenu';
|
||||||
|
|
||||||
import { setLocaleLoaded } from '@/state/localization';
|
import {
|
||||||
|
AppTheme,
|
||||||
|
AppThemeSystemSetting,
|
||||||
|
AppColorMode,
|
||||||
|
setAppThemeSetting,
|
||||||
|
setAppColorMode,
|
||||||
|
} from '@/state/configs';
|
||||||
|
|
||||||
|
import { setLocaleLoaded, setSelectedLocale } from '@/state/localization';
|
||||||
|
import { store } from '@/state/_store';
|
||||||
|
|
||||||
|
import { config } from '@/lib/wagmi';
|
||||||
|
|
||||||
import '@/index.css';
|
import '@/index.css';
|
||||||
import './ladle.css';
|
import './ladle.css';
|
||||||
|
|
||||||
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
|
const wrapProvider = (Component: React.ComponentType<any>, props?: any) => {
|
||||||
|
// eslint-disable-next-line react/display-name
|
||||||
|
return ({ children }: { children: React.ReactNode }) => (
|
||||||
|
<Component {...props}>{children}</Component>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const providers = [
|
||||||
|
wrapProvider(QueryClientProvider, { client: queryClient }),
|
||||||
|
wrapProvider(GrazProvider),
|
||||||
|
wrapProvider(WagmiConfig, { config }),
|
||||||
|
wrapProvider(LocaleProvider),
|
||||||
|
wrapProvider(RestrictionProvider),
|
||||||
|
wrapProvider(DydxProvider),
|
||||||
|
wrapProvider(AccountsProvider),
|
||||||
|
wrapProvider(SubaccountProvider),
|
||||||
|
wrapProvider(DialogAreaProvider),
|
||||||
|
wrapProvider(PotentialMarketsProvider),
|
||||||
|
wrapProvider(AppThemeAndColorModeProvider),
|
||||||
|
];
|
||||||
|
|
||||||
export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
export const StoryWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||||
const [theme, setTheme] = useState('Default theme');
|
const [theme, setTheme] = useState(AppTheme.Classic);
|
||||||
|
const [colorMode, setColorMode] = useState(AppColorMode.GreenUp);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
switch (theme) {
|
store.dispatch(setAppThemeSetting(theme));
|
||||||
case 'Dark theme': {
|
store.dispatch(setAppColorMode(colorMode));
|
||||||
document?.documentElement?.classList.remove('theme-light');
|
}, [theme, colorMode]);
|
||||||
document?.documentElement?.classList.add('theme-dark');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'Light theme': {
|
|
||||||
document?.documentElement?.classList.remove('theme-dark');
|
|
||||||
document?.documentElement?.classList.add('theme-light');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
document?.documentElement?.classList.remove('theme-dark', 'theme-light');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [theme]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
store.dispatch(setSelectedLocale({ locale: SupportedLocales.EN }));
|
||||||
store.dispatch(setLocaleLoaded(true));
|
store.dispatch(setLocaleLoaded(true));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const content = [...providers].reverse().reduce(
|
||||||
|
(children, Provider) => {
|
||||||
|
return <Provider>{children}</Provider>;
|
||||||
|
},
|
||||||
|
<StoryContent>
|
||||||
|
<GlobalStyle />
|
||||||
|
{children}
|
||||||
|
</StoryContent>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<StoryHeader>
|
<StoryHeader>
|
||||||
<h4>Active Theme:</h4>
|
<h4>Active Theme:</h4>
|
||||||
<SelectMenu
|
<SelectMenu value={theme} onValueChange={setTheme}>
|
||||||
value={theme}
|
|
||||||
onValueChange={setTheme}
|
|
||||||
>
|
|
||||||
{[
|
{[
|
||||||
{
|
{
|
||||||
value: 'Default theme',
|
value: AppTheme.Classic,
|
||||||
label: 'Default theme',
|
label: 'Default theme',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'Dark theme',
|
value: AppThemeSystemSetting.System,
|
||||||
|
label: 'System theme',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: AppTheme.Dark,
|
||||||
label: 'Dark theme',
|
label: 'Dark theme',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'Light theme',
|
value: AppTheme.Light,
|
||||||
label: 'Light theme',
|
label: 'Light theme',
|
||||||
},
|
},
|
||||||
].map(({ value, label }) => (
|
].map(({ value, label }) => (
|
||||||
<SelectItem
|
<SelectItem key={value} value={value} label={label} />
|
||||||
key={value}
|
))}
|
||||||
value={value}
|
</SelectMenu>
|
||||||
label={label}
|
<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} />
|
||||||
))}
|
))}
|
||||||
</SelectMenu>
|
</SelectMenu>
|
||||||
</StoryHeader>
|
</StoryHeader>
|
||||||
<hr />
|
<hr />
|
||||||
<StoryContent>{children}</StoryContent>
|
{content}
|
||||||
</Provider>
|
</Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
|
public/
|
||||||
|
|||||||
43
LICENSE
@ -1,48 +1,9 @@
|
|||||||
Subject to your compliance with applicable law, you are granted the right to use the Licensed Work (defined below) under the terms of the below licenses; provided, however, that if you violate any such applicable law in your use of the Licensed Work, all of your rights and licenses to use (including any rights to reproduce, distribute, install or modify) the Licensed Work will automatically and immediately terminate.
|
|
||||||
|
|
||||||
Use of this software before the Change Date specified in the LICENSE file is governed by the Business Source License included in the LICENSE file and at https://spdx.org/licenses/BUSL-1.1.html.
|
|
||||||
|
|
||||||
On and after the Change Date specified in the LICENSE file, use of this software will be governed by the Change License (GNU Affero GPL v3) as specified in the LICENSE file.
|
|
||||||
|
|
||||||
|
|
||||||
Business Source License 1.1
|
|
||||||
Business Source License text copyright © 2023 MariaDB plc, All Rights Reserved. “Business Source License” is a trademark of MariaDB plc.
|
|
||||||
Copyright (C) 2023 dYdX Trading Inc.
|
Copyright (C) 2023 dYdX Trading Inc.
|
||||||
|
|
||||||
Parameters
|
Subject to your compliance with applicable law and the v4 Terms of Use, available at dydx.exchange/legal, you are granted the right to use the Program or Licensed Work (defined below) under the terms of the GNU Affero General Public License as set forth below; provided, however, that if you violate any such applicable law in your use of the Program or Licensed Work, all of your rights and licenses to use (including any rights to reproduce, distribute, install or modify) the Program or Licensed Work will automatically and immediately terminate.
|
||||||
Licensor: dYdX Trading Inc.
|
|
||||||
Licensed Work: dydxprotocol/cosmos-sdk, dydxprotocol/cometbft, dydxprotocol/v4-chain, dydxprotocol/v4-clients, dydxprotocol/v4-web, dydxprotocol/v4-abacus, dydxprotocol/v4-localization, dydxprotocol/v4-documentation, and any dYdX or dYdX Trading Inc. github repository reflecting a copy of this license, or link to this license.
|
|
||||||
Additional Use Grant: None
|
|
||||||
Change Date: On the later to occur of (i) the release of the Licensed Work labeled “dYdX Version 1.0 Affero GPL”, and which includes a document uploaded to the relevant github repository stating “The software in this repository is Version 1.0, subject to Affero GPL license”, and (ii) September 30, 2023 (approximate projected release of “Version 1.0” of this software).
|
|
||||||
Change License: GNU Affero GPL License v3
|
|
||||||
|
|
||||||
License text copyright © 2023 MariaDB plc, All Rights Reserved. “Business Source License” is a trademark of MariaDB plc.
|
|
||||||
Terms
|
|
||||||
The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use.
|
|
||||||
Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate.
|
|
||||||
If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work.
|
|
||||||
All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor.
|
|
||||||
You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work.
|
|
||||||
Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work.
|
|
||||||
This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License).TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE. MariaDB hereby grants you permission to use this License’s text to license your works, and to refer to it using the trademark “Business Source License”, as long as you comply with the Covenants of Licensor below.
|
|
||||||
Covenants of Licensor
|
|
||||||
In consideration of the right to use this License’s text and the “Business Source License” name and trademark, Licensor covenants to MariaDB, and to all other recipients of the licensed work to be provided by Licensor:
|
|
||||||
To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where “compatible” means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation.
|
|
||||||
To either: (a) specify an additional grant of rights to use that does not impose any additional restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the text “None” to specify a Change Date. Not to modify this License in any other way.
|
|
||||||
Notice
|
|
||||||
The Business Source License (this document, or the “License”) is not an Open Source license. However, the Licensed Work will eventually be made available under an Open Source License, as stated in this License.
|
|
||||||
|
|
||||||
|
|
||||||
|
The “Program” or “Licensed Work” shall mean any of the following: dydxprotocol/cosmos-sdk, dydxprotocol/cometbft, dydxprotocol/v4-chain, dydxprotocol/v4-clients, dydxprotocol/v4-web, dydxprotocol/v4-abacus, dydxprotocol/v4-localization, dydxprotocol/v4-documentation, and any dYdX or dYdX Trading Inc. repository reflecting a copy of, or link to, this license.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OPEN SOURCE LICENSE BELOW - TO BE APPLIED AFTER THE CHANGE DATE.
|
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2023 dYdX Trading Inc.
|
|
||||||
|
|
||||||
Subject to your compliance with applicable law, you are granted the right to use the Licensed Work (defined below) under the terms of the GNU Affero General Public License as set forth below; provided, however, that if you violate any such applicable law in your use of the Licensed Work, all of your rights and licenses to use (including any rights to reproduce, distribute, install or modify) the Licensed Work will automatically and immediately terminate.
|
|
||||||
|
|
||||||
|
|
||||||
The GNU Affero General Public License
|
The GNU Affero General Public License
|
||||||
|
|||||||
67
README.md
@ -1,10 +1,10 @@
|
|||||||
<p align="center"><img src="https://dydx.exchange/icon.svg?" width="256" /></p>
|
<p align="center"><img src="https://dydx.exchange/icon.svg?" width="256" /></p>
|
||||||
|
|
||||||
<h1 align="center">v4 Web</h1>
|
<h1 align="center">dYdX Chain Web</h1>
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href='https://github.com/dydxprotocol/v4-web/blob/main/LICENSE'>
|
<a href='https://github.com/dydxprotocol/v4-web/blob/main/LICENSE'>
|
||||||
<img src='https://img.shields.io/badge/License-BSL_1.1-blue' alt='License' />
|
<img src='https://img.shields.io/badge/License-AGPL_v3-blue.svg' alt='License' />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ Alternatively, follow the [IPFS Kubo installation guide](https://docs.ipfs.tech
|
|||||||
|
|
||||||
## Part 1: Setting up your local environment
|
## Part 1: Setting up your local environment
|
||||||
|
|
||||||
### Step 1: Clone the repo
|
### 1. Clone the repo
|
||||||
|
|
||||||
Clone the repository and navigate to its directory:
|
Clone the repository and navigate to its directory:
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ git clone https://github.com/dydxprotocol/v4-web.git
|
|||||||
cd v4-web
|
cd v4-web
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 2: Install pnpm and dependencies
|
### 2. Install pnpm and dependencies
|
||||||
|
|
||||||
Install pnpm and the project dependencies:
|
Install pnpm and the project dependencies:
|
||||||
|
|
||||||
@ -66,10 +66,30 @@ This will automatically open your default browser at `http://localhost:61000`.
|
|||||||
|
|
||||||
Add or modify the relevant endpoints, links and options in `/public/configs/env.json`.
|
Add or modify the relevant endpoints, links and options in `/public/configs/env.json`.
|
||||||
You'll need to provide a Wallet Connect project id to enable onboarding and wallet connection:
|
You'll need to provide a Wallet Connect project id to enable onboarding and wallet connection:
|
||||||
|
|
||||||
- Create a project on https://cloud.walletconnect.com/app
|
- Create a project on https://cloud.walletconnect.com/app
|
||||||
- Copy over the project ID into this [field](https://github.com/dydxprotocol/v4-web/blob/67ecbd75b43e0c264b7b4d2d9b3d969830b0621c/public/configs/env.json#L822C33-L822C46)
|
- Copy over the project ID into this [field](https://github.com/dydxprotocol/v4-web/blob/67ecbd75b43e0c264b7b4d2d9b3d969830b0621c/public/configs/env.json#L822C33-L822C46)
|
||||||
|
|
||||||
## Part 4: Deploying with Vercel
|
## Part 4: Set Enviornment variables
|
||||||
|
|
||||||
|
Set environment variables via `.env`.
|
||||||
|
|
||||||
|
- `VITE_BASE_URL` (required): The base URL of the deployment (e.g., `https://www.example.com`).
|
||||||
|
- `VITE_ALCHEMY_API_KEY` (optional): Add an Alchemy API key for EVM interactions; the app will fall back to public RPCs if not provided.
|
||||||
|
- `VITE_PK_ENCRYPTION_KEY` (optional): AES encryption key used for signature obfuscation; necessary for enabling the "Remember Me" feature.
|
||||||
|
- `VITE_V3_TOKEN_ADDRESS` (optional): Address of the V3 $DYDX token.
|
||||||
|
- `VITE_TOKEN_MIGRATION_URI` (optional): The URL of the token migration website.
|
||||||
|
- `AMPLITUDE_API_KEY` (optional): Amplitude API key for enabling Amplitude; used with `pnpm run build:inject-amplitude`.
|
||||||
|
- `AMPLITUDE_SERVER_URL` (optional): Custom Amplitude server URL
|
||||||
|
- `BUGSNAG_API_KEY` (optional): API key for enabling Bugsnag; used with `pnpm run build:inject-bugsnag`.
|
||||||
|
- `IOS_APP_ID` (optional): iOS app ID used for enabling deep linking to the iOS app; used with `pnpm run build:inject-app-deeplinks`.
|
||||||
|
- `INTERCOM_APP_ID` (optional): Used for enabling Intercom; utilized with `pnpm run build:inject-intercom`.
|
||||||
|
- `STATUS_PAGE_SCRIPT_URI` (optional): Used for enabling the status page; used with `pnpm run build:inject-statuspage`.
|
||||||
|
- `SMARTBANNER_APP_NAME`, `SMARTBANNER_ORG_NAME`, `SMARTBANNER_ICON_URL`, `SMARTBANNER_APPSTORE_URL` (optional): Used for enabling the smart app banner; used with `pnpm run build:inject-smartbanner`.
|
||||||
|
|
||||||
|
# Deployments
|
||||||
|
|
||||||
|
## Deploying with Vercel
|
||||||
|
|
||||||
### Step 1: Connect your repository to Vercel
|
### Step 1: Connect your repository to Vercel
|
||||||
|
|
||||||
@ -78,15 +98,33 @@ Select "Import Git Repository" from your dashboard, and provide the URL of this
|
|||||||
### Step 2: Configure your project
|
### Step 2: Configure your project
|
||||||
|
|
||||||
For the "Build & Development Settings", we recommend the following:
|
For the "Build & Development Settings", we recommend the following:
|
||||||
|
|
||||||
- Framework Preset: `Vite`
|
- Framework Preset: `Vite`
|
||||||
- Build Command (override): `pnpm run build`
|
- Build Command (override): `pnpm run build`
|
||||||
|
|
||||||
|
By default, the dev server runs in development mode and the build command runs in production mode. To override the default mode, you can pass in the `--mode` option flag. For example, if you want to build your app for testnet:
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm run build --mode testnet
|
||||||
|
```
|
||||||
|
|
||||||
If you wish to incorporate analytics via Amplitude and Bugsnag, you can use our scripts:
|
If you wish to incorporate analytics via Amplitude and Bugsnag, you can use our scripts:
|
||||||
`pnpm run build:inject-amplitude` and `pnpm run build:inject-bugsnag`. You will need to provide your own API keys for these services. In the Environment Variables section, name the variables as `AMPLITUDE_API_KEY` and `BUGSNAG_API_KEY` and provide the respective keys as their values.
|
`pnpm run build:inject-amplitude` and `pnpm run build:inject-bugsnag`. You will need to provide your own API keys for these services. In the Environment Variables section, name the variables as `AMPLITUDE_API_KEY` and `BUGSNAG_API_KEY` and provide the respective keys as their values.
|
||||||
|
|
||||||
|
If you wish to incorporate smart banner for iOS and/or Android apps, you can use our scripts:
|
||||||
|
`pnpm run build:inject-smartbanner`. You will need to provide your own app configurations for these services. In the Environment Variables section, name the variables as `SMARTBANNER_APP_NAME`, `SMARTBANNER_ORG_NAME`, `SMARTBANNER_ICON_URL` and `SMARTBANNER_APPSTORE_URL` or `SMARTBANNER_GOOGLEPLAY_URL` and provide the respective values.
|
||||||
|
|
||||||
For more details, check out Vercel's [official documentation](https://vercel.com/docs).
|
For more details, check out Vercel's [official documentation](https://vercel.com/docs).
|
||||||
|
|
||||||
## Part 5: Deploying to IPFS
|
## Deploying to IPFS
|
||||||
|
|
||||||
|
### Must Enable HashRouting
|
||||||
|
|
||||||
|
Add the following to `.env` file
|
||||||
|
|
||||||
|
```
|
||||||
|
VITE_ROUTER_TYPE=hash
|
||||||
|
```
|
||||||
|
|
||||||
### web3.storage: deploy to IPFS via web3.storage using the provided script
|
### web3.storage: deploy to IPFS via web3.storage using the provided script
|
||||||
|
|
||||||
@ -118,3 +156,20 @@ To access your content on IPFS:
|
|||||||
2. **Public IPFS gateway:** Access your content via a public IPFS gateway, such as [https://dweb.link](https://dweb.link/) or [https://w3s.link/](https://w3s.link/). Use the gateway URL with your CID appended, like `https://dweb.link/ipfs/your_cid`.
|
2. **Public IPFS gateway:** Access your content via a public IPFS gateway, such as [https://dweb.link](https://dweb.link/) or [https://w3s.link/](https://w3s.link/). Use the gateway URL with your CID appended, like `https://dweb.link/ipfs/your_cid`.
|
||||||
|
|
||||||
Replace `your_cid` with the actual CID.
|
Replace `your_cid` with the actual CID.
|
||||||
|
|
||||||
|
## Cloudflare Settings
|
||||||
|
|
||||||
|
We recommend that you add your website to Cloudflare for additional security settings.
|
||||||
|
|
||||||
|
To block OFAC Sanctioned countries:
|
||||||
|
|
||||||
|
1. Navigate Websites > Domain > Security > WAF
|
||||||
|
|
||||||
|
2. Create Rule with the following settings:
|
||||||
|
|
||||||
|
- If incoming requests match
|
||||||
|
`(ip.geoip.country eq "CU") or (ip.geoip.country eq "IR") or (ip.geoip.country eq "KP") or (ip.geoip.country eq "SY") or (ip.geoip.country eq "MM") or (ip.geoip.subdivision_1_iso_code eq "UA-09") or (ip.geoip.subdivision_1_iso_code eq "UA-14") or (ip.geoip.subdivision_1_iso_code eq "UA-43")`
|
||||||
|
- This rule will bring up a Cloudflare page when a restricted geography tries to access your site. You will have the option to display:
|
||||||
|
1. Custom Text
|
||||||
|
- (e.g. `Because you appear to be a resident of, or trading from, a jurisdiction that violates our terms of use, or have engaged in activity that violates our terms of use, you have been blocked. You may withdraw your funds from the protocol at any time.`)
|
||||||
|
2. Default Cloudflare WAF block page
|
||||||
|
|||||||
39
package.json
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "dydx-chain-web",
|
"name": "dydx-chain-web",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.1",
|
"version": "1.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "BSL-1.1",
|
"license": "AGPL-3.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
@ -15,6 +15,7 @@
|
|||||||
"build:inject-bugsnag": "node scripts/inject-bugsnag.js",
|
"build:inject-bugsnag": "node scripts/inject-bugsnag.js",
|
||||||
"build:inject-intercom": "node scripts/inject-intercom.js",
|
"build:inject-intercom": "node scripts/inject-intercom.js",
|
||||||
"build:inject-statuspage": "node scripts/inject-statuspage.js",
|
"build:inject-statuspage": "node scripts/inject-statuspage.js",
|
||||||
|
"build:inject-smartbanner": "node scripts/inject-smartbanner.js",
|
||||||
"deploy:ipfs": "node scripts/upload-ipfs.js --verbose",
|
"deploy:ipfs": "node scripts/upload-ipfs.js --verbose",
|
||||||
"deploy:update-ipns": "node scripts/update-ipns.js",
|
"deploy:update-ipns": "node scripts/update-ipns.js",
|
||||||
"deploy:update-dnslink": "node scripts/update-dnslink.js",
|
"deploy:update-dnslink": "node scripts/update-dnslink.js",
|
||||||
@ -33,20 +34,23 @@
|
|||||||
"packageManager": "pnpm@8.6.6",
|
"packageManager": "pnpm@8.6.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0xsquid/sdk": "^1.10.0",
|
"@0xsquid/sdk": "^1.10.0",
|
||||||
"@cosmjs/amino": "^0.31.0",
|
"@cosmjs/amino": "^0.32.1",
|
||||||
"@cosmjs/crypto": "^0.31.0",
|
"@cosmjs/crypto": "^0.32.1",
|
||||||
"@cosmjs/encoding": "^0.31.0",
|
"@cosmjs/encoding": "^0.32.1",
|
||||||
"@cosmjs/proto-signing": "^0.31.0",
|
"@cosmjs/proto-signing": "^0.32.1",
|
||||||
"@cosmjs/stargate": "^0.31.0",
|
"@cosmjs/stargate": "^0.32.1",
|
||||||
"@cosmjs/tendermint-rpc": "^0.31.0",
|
"@cosmjs/tendermint-rpc": "^0.32.1",
|
||||||
"@dydxprotocol/v4-abacus": "^0.7.6",
|
"@dydxprotocol/v4-abacus": "^1.4.12",
|
||||||
"@dydxprotocol/v4-client-js": "^0.40.3",
|
"@dydxprotocol/v4-client-js": "^1.0.20",
|
||||||
"@dydxprotocol/v4-localization": "^0.1.32",
|
"@dydxprotocol/v4-localization": "^1.1.35",
|
||||||
"@ethersproject/providers": "^5.7.2",
|
"@ethersproject/providers": "^5.7.2",
|
||||||
"@js-joda/core": "^5.5.3",
|
"@js-joda/core": "^5.5.3",
|
||||||
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-collapsible": "^1.0.3",
|
"@radix-ui/react-collapsible": "^1.0.3",
|
||||||
"@radix-ui/react-dialog": "^1.0.4",
|
"@radix-ui/react-dialog": "^1.0.4",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
||||||
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-navigation-menu": "^1.1.3",
|
"@radix-ui/react-navigation-menu": "^1.1.3",
|
||||||
"@radix-ui/react-popover": "^1.0.6",
|
"@radix-ui/react-popover": "^1.0.6",
|
||||||
"@radix-ui/react-radio-group": "^1.1.3",
|
"@radix-ui/react-radio-group": "^1.1.3",
|
||||||
@ -89,6 +93,7 @@
|
|||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"cmdk": "^0.2.0",
|
"cmdk": "^0.2.0",
|
||||||
"color": "^4.2.3",
|
"color": "^4.2.3",
|
||||||
|
"cosmjs-types": "^0.9.0",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"ethers": "^6.6.1",
|
"ethers": "^6.6.1",
|
||||||
"graz": "^0.0.43",
|
"graz": "^0.0.43",
|
||||||
@ -96,6 +101,7 @@
|
|||||||
"long": "^5.2.3",
|
"long": "^5.2.3",
|
||||||
"luxon": "^3.3.0",
|
"luxon": "^3.3.0",
|
||||||
"qr-code-styling": "1.6.0-rc.1",
|
"qr-code-styling": "1.6.0-rc.1",
|
||||||
|
"query-string": "^8.1.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-aria": "^3.25.0",
|
"react-aria": "^3.25.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
@ -107,12 +113,12 @@
|
|||||||
"reselect": "^4.1.8",
|
"reselect": "^4.1.8",
|
||||||
"styled-components": "^5.3.11",
|
"styled-components": "^5.3.11",
|
||||||
"use-latest": "^1.2.1",
|
"use-latest": "^1.2.1",
|
||||||
"viem": "^1.12.2",
|
"viem": "^1.20.0",
|
||||||
"wagmi": "^1.3.7"
|
"wagmi": "^1.4.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.22.5",
|
"@babel/core": "^7.22.5",
|
||||||
"@ladle/react": "^2.15.0",
|
"@ladle/react": "^4.0.2",
|
||||||
"@types/color": "^3.0.3",
|
"@types/color": "^3.0.3",
|
||||||
"@types/crypto-js": "^4.1.1",
|
"@types/crypto-js": "^4.1.1",
|
||||||
"@types/luxon": "^3.3.0",
|
"@types/luxon": "^3.3.0",
|
||||||
@ -151,5 +157,10 @@
|
|||||||
"vitest": "^0.32.2",
|
"vitest": "^0.32.2",
|
||||||
"w3name": "^1.0.8",
|
"w3name": "^1.0.8",
|
||||||
"web3.storage": "^4.5.4"
|
"web3.storage": "^4.5.4"
|
||||||
|
},
|
||||||
|
"pnpm": {
|
||||||
|
"overrides": {
|
||||||
|
"follow-redirects": "1.15.3"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4233
pnpm-lock.yaml
generated
@ -8,67 +8,43 @@
|
|||||||
],
|
],
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
"/": "/trade/*"
|
"/": "/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/": "/r/*"
|
"/": "/#/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/": "/portfolio/overview"
|
"/": "*/markets"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/": "/portfolio/positions"
|
"/": "*/trade"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/": "/portfolio/orders"
|
"/": "*/trade/*"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/": "/portfolio/fees"
|
"/": "*/portfolio"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/": "/portfolio/history"
|
"/": "*/portfolio/overview"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/": "/portfolio/history/trades"
|
"/": "*/portfolio/positions"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/": "/portfolio/history/transfers"
|
"/": "*/portfolio/orders"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/": "/portfolio/history/funding"
|
"/": "*/portfolio/fees"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/": "/rewards"
|
"/": "*/portfolio/history/trades"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/": "/my-profile"
|
"/": "*/portfolio/history/transfers"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/": "/rankings/hedgies"
|
"/": "*/portfolio/history/funding"
|
||||||
},
|
|
||||||
{
|
|
||||||
"/": "/rankings/competition"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/": "/rankings/diamond"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/": "/rankings/platinum"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/": "/rankings/gold"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/": "/rankings/silver"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/": "/rankings/bronze"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/": "/rankings/pnl-absolute"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/": "/rankings/pnl-percent"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/": "/walletsegue",
|
"/": "/walletsegue",
|
||||||
|
|||||||
22
public/.well-known/assetlinks.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||||
|
"target": {
|
||||||
|
"namespace": "android_app",
|
||||||
|
"package_name": "exchange.dydx.trading.debug",
|
||||||
|
"sha256_cert_fingerprints": [
|
||||||
|
"8A:9C:CC:49:B0:35:9A:91:67:CB:98:B0:B5:87:92:5F:9E:B7:EF:CE:A0:47:57:85:A4:35:3E:0C:E1:56:9E:A2"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||||
|
"target": {
|
||||||
|
"namespace": "android_app",
|
||||||
|
"package_name": "exchange.dydx.trading",
|
||||||
|
"sha256_cert_fingerprints": [
|
||||||
|
"B2:2D:CC:27:9D:52:05:98:63:C9:7B:34:36:70:A3:8E:00:31:28:08:2D:2E:70:76:C9:31:AE:F9:55:21:15:A5"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
Before Width: | Height: | Size: 122 KiB |
19
public/chart-bars-background.svg
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<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>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
20
public/chart-bars.svg
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<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>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
20484
public/chart-dots-background-dark.svg
Normal file
|
After Width: | Height: | Size: 2.2 MiB |
20484
public/chart-dots-background-light.svg
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
22
public/configs/cctp.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"chainId": "1",
|
||||||
|
"tokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
||||||
|
"name": "Ethereum"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chainId": "5",
|
||||||
|
"tokenAddress": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F",
|
||||||
|
"name": "Ethereum Goerli"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chainId": "43114",
|
||||||
|
"tokenAddress": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
|
||||||
|
"name": "Avalanche"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chainId": "10",
|
||||||
|
"tokenAddress": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
|
||||||
|
"name": "optimism"
|
||||||
|
}
|
||||||
|
]
|
||||||
16
public/configs/documentation.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"tradingRewardsFAQs": [
|
||||||
|
{
|
||||||
|
"questionLocalizationKey": "APP.TRADING_REWARDS.FAQ_WHO_IS_ELIGIBLE_QUESTION",
|
||||||
|
"answerLocalizationKey": "APP.TRADING_REWARDS.FAQ_WHO_IS_ELIGIBLE_ANSWER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"questionLocalizationKey": "APP.TRADING_REWARDS.FAQ_HOW_DO_TRADING_REWARDS_WORK_QUESTION",
|
||||||
|
"answerLocalizationKey": "APP.TRADING_REWARDS.FAQ_HOW_DO_TRADING_REWARDS_WORK_ANSWER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"questionLocalizationKey": "APP.TRADING_REWARDS.FAQ_HOW_DO_I_CLAIM_MY_REWARDS_QUESTION",
|
||||||
|
"answerLocalizationKey": "APP.TRADING_REWARDS.FAQ_HOW_DO_I_CLAIM_MY_REWARDS_ANSWER"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
8
public/configs/exchanges.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "coinbase",
|
||||||
|
"label": "Coinbase",
|
||||||
|
"icon": "/exchanges/coinbase.png",
|
||||||
|
"depositType": "noble"
|
||||||
|
}
|
||||||
|
]
|
||||||
1
public/configs/otherMarketDisclaimer.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
This file identifies parameters for the optimal performance of various assets with the dYdX v4 open source software ("dYdX Chain"). For information on which assets are likely to be best compatible with dYdX Chain and how likely software compatibility and optimal parameters are assessed, please review the documentation [here](https://docs.dydx.trade/governance/proposing_a_new_market#example-proposal-json). Users considering using the permissionless markets function of the dYdX Chain are encouraged to consult qualified legal counsel to ensure compliance with the laws of their jurisdiction. The information herein does not constitute and should not be relied on as an endorsement or recommendation for any specific market, or investment, legal, or any other form of professional advice. Use of the v4 software is prohibited in the United States, Canada, and sanctioned jurisdictions as described in the [v4 Terms of Use](https://dydx.exchange/v4-terms).
|
||||||
616
public/configs/otherMarketExchangeConfig.json
Normal file
@ -0,0 +1,616 @@
|
|||||||
|
{
|
||||||
|
"1INCH": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "1INCHUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "1INCH-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "1INCH_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "1INCH-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "1INCH-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "1INCH_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"AAVE": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "AAVEUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "AAVE-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "aaveusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "AAVEUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "AAVE-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "AAVE-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "AAVE_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"ADA": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "ADAUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bitstamp", "ticker": "ADA/USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "ADAUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "ADA-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "adausdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "ADAUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "ADA-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "ADA-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "ADA_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"AGIX": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "AGIXUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "AGIXUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "AGIX_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "AGIX-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "AGIX-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "AGIX_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"ALGO": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "ALGOUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "ALGO-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "ALGOUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "ALGO-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "ALGO-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "ALGO_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"APE": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "APEUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "APE-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "APE_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "APEUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "APE-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "APE-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "APE_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"APT": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "APTUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "APTUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "APT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "APT_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "aptusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "APTUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "APT-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "APT-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "APT_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"ARB": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "ARBUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "ARBUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "ARB-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "arbusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "ARBUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "ARB-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "ARB-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "ARB_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"ATOM": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "ATOMUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "ATOMUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "ATOM-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "ATOM_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "ATOMUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "ATOM-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "ATOM-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "ATOM_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"AVAX": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "AVAXUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bitstamp", "ticker": "AVAX/USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "AVAXUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "AVAX-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "avaxusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "AVAXUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "AVAX-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "AVAX-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "AVAX_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"BCH": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "BCHUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bitstamp", "ticker": "BCH/USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "BCHUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "BCH-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "bchusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "BCHUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "BCH-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "BCH-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "BCH_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"BLUR": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "BLURUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "BLURUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "BLUR-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "BLURUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "BLUR-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "BLUR-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "BLUR_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"BNB": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "BNBUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "BNBUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "BNB_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "BNB-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "BNB-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "BNB_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"BONK": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "BONKUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "BONKUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "BONK-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "BONK-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "BONK-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "BONK_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"BTC": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "BTCUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bitstamp", "ticker": "BTC/USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "BTCUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "BTC-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "btcusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "BTCUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "BTC-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "BTC-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "BTC_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"CHZ": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "CHZUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "CHZ-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "CHZUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "CHZ-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "CHZ-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "CHZ_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"CRV": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "CRVUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "CRV-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "CRVUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "CRV-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "CRV-USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"DOGE": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "DOGEUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "DOGEUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "DOGE-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "dogeusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "DOGEUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "DOGE-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "DOGE-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "DOGE_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"DOT": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "DOTUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "DOTUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "DOT-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "dotusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "DOTUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "DOT-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "DOT-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "DOT_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"DYM": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "DYMUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "DYMUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "DYM_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "DYM-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "DYM_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"ENS": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "ENSUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "ENS-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "ENS_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "ENS-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "ENS-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "ENS_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"EOS": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "EOSUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "EOSUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "EOS-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "EOS_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "EOSUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "EOS-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "EOS-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "EOS_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"ETC": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "ETCUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "ETCUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "ETC-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "etcusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "ETCUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "ETC-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "ETC-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "ETC_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"ETH": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "ETHUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bitstamp", "ticker": "ETH/USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "ETHUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "ETH-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "ethusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "ETHUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "ETH-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "ETH-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "ETH_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"FET": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "FETUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "FET-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "FETUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "FET-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "FET-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "FET_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"FIL": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "FILUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "FILUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "FIL-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "filusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "FILUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "FIL-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "FIL-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "FIL_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"FTM": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "FTMUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "FTMUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "FTMUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "FTM-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "FTM-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "FTM_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"GALA": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "GALAUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "GALAUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "GALA_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "GALAUSD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "GALA-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "GALA_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"GMT": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "GMTUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "GMTUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "GMT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "GMT_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "GMT-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "GMT-USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"GRT": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "GRTUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "GRT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "GRT_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "GRTUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "GRT-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "GRT-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "GRT_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"HBAR": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "HBARUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "HBARUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "HBAR-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "HBAR-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "HBAR-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "HBAR_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"ICP": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "ICPUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "ICPUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "ICP-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "ICPUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "ICP-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "ICP-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "ICP_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"IMX": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "IMXUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "IMX-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "IMXUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "IMX-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "IMX-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "IMX_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"INJ": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "INJUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "INJUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "INJ-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "INJUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "INJ-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "INJ-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "INJ_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"JTO": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "JTOUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "JTOUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "JTO-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "JTO-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "JTO-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "JTO_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"JUP": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "JUPUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "JUPUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "JUP_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "JUP-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "JUP_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"KAVA": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "KAVAUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "KAVAUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "KAVA-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "KAVA_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "KAVAUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "KAVA-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "KAVA_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"LDO": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "LDOUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "LDOUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "LDO-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "LDOUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "LDO-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "LDO-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "LDO_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"LINK": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "LINKUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bitstamp", "ticker": "LINK/USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "LINKUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "LINK-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "LINKUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "LINK-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "LINK-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "LINK_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"LTC": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "LTCUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bitstamp", "ticker": "LTC/USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "LTCUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "LTC-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "ltcusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "LTCUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "LTC-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "LTC-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "LTC_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"MANA": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "MANAUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "MANA-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "MANA_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "MANAUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "MANA-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "MANA-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "MANA_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"MASK": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "MASKUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "MASKUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "MASK-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "MASK_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "maskusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "MASK-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "MASK-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "MASK_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"MATIC": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "MATICUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bitstamp", "ticker": "MATIC/USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "MATICUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "MATIC-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "maticusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "MATICUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "MATIC-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "MATIC-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "MATIC_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"MINA": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "MINAUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "MINA-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "MINA_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "MINAUSD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "MINA-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "MINA_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"MKR": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "MKRUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "MKR-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "MKRUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "MKR-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "MKR-USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"NEAR": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "NEARUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "NEARUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "NEAR-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "nearusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "NEARUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "NEAR-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "NEAR-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "NEAR_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"OP": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "OPUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "OPUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "OP-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "OP_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "OPUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "OP-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "OP-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "OP_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"ORDI": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "ORDIUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "ORDIUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "ORDI_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "ordiusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "ORDI-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "ORDI-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "ORDI_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"PEPE": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "PEPEUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "PEPEUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "PEPEUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "PEPE-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "PEPE-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "PEPE_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"PYTH": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "PYTHUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "PYTHUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "PYTH_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "PYTH-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "PYTH-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "PYTH_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"RNDR": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "RNDRUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "RNDR-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "RNDRUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "RNDR-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "RNDR-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "RNDR_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"RUNE": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "RUNEUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "RUNE_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "RUNEUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "RUNE-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "RUNE_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"SAND": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "SANDUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "SAND-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "SAND_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "SAND-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "SAND-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "SAND_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"SEI": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "SEIUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "SEIUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "SEI-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "seiusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "SEIUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "SEI-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "SEI_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"SHIB": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "SHIBUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "SHIBUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "SHIB-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "shibusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "SHIBUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "SHIB-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "SHIB-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "SHIB_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"SNX": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "SNXUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "SNXUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "SNX-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "SNXUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "SNX-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "SNX-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "SNX_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"SOL": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "SOLUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bitstamp", "ticker": "SOL/USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "SOLUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "SOL-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "solusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "SOLUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "SOL-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "SOL-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "SOL_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"STRK": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "STRKUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "STRKUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "STRKUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "STRK-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "STRK-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "STRK_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"STX": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "STXUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "STXUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "STX-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "STX_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "STXUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "STX-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "STX-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "STX_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"SUI": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "SUIUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "SUIUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "SUI-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "suiusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "SUIUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "SUI-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "SUI-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "SUI_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"TIA": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "TIAUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "TIAUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "TIA-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "TIAUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "TIA-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "TIA-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "TIA_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"TRX": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "TRXUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "TRXUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "TRX_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "trxusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "TRXUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "TRX-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "TRX-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "TRX_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"UNI": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "UNIUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "UNIUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "UNI-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "UNIUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "UNI-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "UNI-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "UNI_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"WLD": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "WLDUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "WLDUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "WLD_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "WLD-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "WLD-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "WLD_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"WOO": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "WOOUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "WOO_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "WOO-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "WOO-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "WOO_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"XLM": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "XLMUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bitstamp", "ticker": "XLM/USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "XLMUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "XLM-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "XLMUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "XLM-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "XLM-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "XLM_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"XRP": [
|
||||||
|
{ "exchangeName": "Binance", "ticker": "XRPUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Bitstamp", "ticker": "XRP/USD" },
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "XRPUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "XRP-USD" },
|
||||||
|
{ "exchangeName": "Huobi", "ticker": "xrpusdt", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kraken", "ticker": "XRPUSD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "XRP-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "XRP-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "XRP_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
],
|
||||||
|
"ZETA": [
|
||||||
|
{ "exchangeName": "Bybit", "ticker": "ZETAUSDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "CoinbasePro", "ticker": "ZETA-USD" },
|
||||||
|
{ "exchangeName": "Gate", "ticker": "ZETA_USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Kucoin", "ticker": "ZETA-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Okx", "ticker": "ZETA-USDT", "adjustByMarket": "USDT-USD" },
|
||||||
|
{ "exchangeName": "Mexc", "ticker": "ZETA_USDT", "adjustByMarket": "USDT-USD" }
|
||||||
|
]
|
||||||
|
}
|
||||||
1158
public/configs/otherMarketParameters.json
Normal file
656
public/configs/v1/env.json
Normal file
@ -0,0 +1,656 @@
|
|||||||
|
{
|
||||||
|
"apps": {
|
||||||
|
"ios": {
|
||||||
|
"scheme": "dydx-t-v4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tokens": {
|
||||||
|
"dydxprotocol-testnet": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydx-testnet-4": {
|
||||||
|
"chain": {
|
||||||
|
"name": "Dv4TNT",
|
||||||
|
"denom": "adv4tnt",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"[mainnet chain id]": {
|
||||||
|
"comment": "Change according to mainnet release",
|
||||||
|
"chain": {
|
||||||
|
"name": "TokenName",
|
||||||
|
"denom": "tokenDenom",
|
||||||
|
"decimals": 18,
|
||||||
|
"image": "/currencies/dydx.png"
|
||||||
|
},
|
||||||
|
"usdc": {
|
||||||
|
"name": "USDC",
|
||||||
|
"denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
|
||||||
|
"gasDenom": "uusdc",
|
||||||
|
"decimals": 6,
|
||||||
|
"image": "/currencies/usdc.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"dydxprotocol-testnet": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"statusPage": "https://status.v4testnet.dydx.exchange/",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog",
|
||||||
|
"foundation": "https://www.dydx.foundation",
|
||||||
|
"help": "https://help.dydx.exchange/",
|
||||||
|
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||||
|
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||||
|
"documentation": "https://docs.dydx.exchange/",
|
||||||
|
"community": "https://discord.com/invite/dydx",
|
||||||
|
"governanceLearnMore": "https://help.dydx.exchange",
|
||||||
|
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||||
|
"stakingLearnMore": "https://help.dydx.exchange",
|
||||||
|
"keplrDashboard": "https://testnet.keplr.app/",
|
||||||
|
"strideZoneApp": "https://testnet.stride.zone",
|
||||||
|
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
|
||||||
|
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
|
||||||
|
"launchIncentive": "https://cloud.chaoslabs.co"
|
||||||
|
},
|
||||||
|
"dydx-testnet-4": {
|
||||||
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
"privacy": "https://dydx.exchange/privacy",
|
||||||
|
"statusPage": "https://status.v4testnet.dydx.exchange/",
|
||||||
|
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||||
|
"documentation": "https://docs.dydx.exchange/",
|
||||||
|
"community": "https://discord.com/invite/dydx",
|
||||||
|
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
|
||||||
|
"blogs": "https://www.dydx.foundation/blog",
|
||||||
|
"foundation": "https://www.dydx.foundation",
|
||||||
|
"help": "https://help.dydx.exchange/",
|
||||||
|
"reduceOnlyLearnMore": "https://help.dydx.exchange/articles/6345793-reduce-only-orders",
|
||||||
|
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||||
|
"governanceLearnMore": "https://help.dydx.exchange",
|
||||||
|
"newMarketProposalLearnMore": "https://dydx.exchange/blog/new-market-proposals",
|
||||||
|
"stakingLearnMore": "https://help.dydx.exchange",
|
||||||
|
"keplrDashboard": "https://testnet.keplr.app/",
|
||||||
|
"strideZoneApp": "https://testnet.stride.zone",
|
||||||
|
"accountExportLearnMore": "https://help.dydx.exchange/en/articles/8565867-secret-phrase-on-dydx-chain",
|
||||||
|
"walletLearnMore": "https://www.dydx.academy/video/defi-wallet",
|
||||||
|
"launchIncentive": "https://cloud.chaoslabs.co"
|
||||||
|
},
|
||||||
|
"[mainnet chain id]": {
|
||||||
|
"tos": "[HTTP link to TOS]",
|
||||||
|
"privacy": "[HTTP link to Privacy Policy]",
|
||||||
|
"statusPage": "[HTTP link to status page]",
|
||||||
|
"mintscan": "[HTTP link to Mintscan, with {tx_hash} placeholder]",
|
||||||
|
"mintscanBase": "[HTTP link to TOS mintscan base url]",
|
||||||
|
"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]",
|
||||||
|
"reduceOnlyLearnMore": "[HTTP link to reduce-only learn more, can be null]",
|
||||||
|
"documentation": "[HTTP link to documentation, can be null]",
|
||||||
|
"community": "[HTTP link to community, can be null]",
|
||||||
|
"help": "[HTTP link to help page, can be null]",
|
||||||
|
"governanceLearnMore": "[HTTP link to governance learn more, can be null]",
|
||||||
|
"newMarketProposalLearnMore": "[HTTP link to new market proposal learn more, can be null]",
|
||||||
|
"stakingLearnMore": "[HTTP link to staking learn more, can be null]",
|
||||||
|
"keplrDashboard": "[HTTP link to keplr dashboard, can be null]",
|
||||||
|
"strideZoneApp": "[HTTP link to stride zone app, can be null]",
|
||||||
|
"accountExportLearnMore": "[HTTP link to account export learn more, can be null]",
|
||||||
|
"walletLearnMore": "[HTTP link to wallet learn more, can be null]",
|
||||||
|
"launchIncentive": "[HTTP link to launch incentive host, can be null]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wallets": {
|
||||||
|
"dydxprotocol-testnet": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX Chain"
|
||||||
|
},
|
||||||
|
"dydx-testnet-4": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "dYdX v4",
|
||||||
|
"description": "dYdX v4 App",
|
||||||
|
"iconUrl": "/logos/dydx-x.png"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "47559b2ec96c09aed9ff2cb54a31ab0e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "/walletsegue"
|
||||||
|
},
|
||||||
|
"images": "/wallets/",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX Chain"
|
||||||
|
},
|
||||||
|
"[mainnet chain id]": {
|
||||||
|
"walletconnect": {
|
||||||
|
"client": {
|
||||||
|
"name": "[Name of the app]",
|
||||||
|
"description": "[Description of the app]",
|
||||||
|
"iconUrl": "[Relative URL of the icon URL]"
|
||||||
|
},
|
||||||
|
"v2": {
|
||||||
|
"projectId": "[Project ID]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"walletSegue": {
|
||||||
|
"callbackUrl": "[Relative callback URL for WalletSegue, should match apple-app-site-association]"
|
||||||
|
},
|
||||||
|
"images": "[Relative URL for wallet images]",
|
||||||
|
"signTypedDataAction": "dYdX Chain Onboarding",
|
||||||
|
"signTypedDataDomainName": "dYdX Chain"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"governance": {
|
||||||
|
"dydxprotocol-testnet": {
|
||||||
|
"newMarketProposal": {
|
||||||
|
"initialDepositAmount": 10000000,
|
||||||
|
"delayBlocks": 900,
|
||||||
|
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydx-testnet-4": {
|
||||||
|
"newMarketProposal": {
|
||||||
|
"initialDepositAmount": 10000000,
|
||||||
|
"delayBlocks": 900,
|
||||||
|
"newMarketsMethodology": "https://docs.google.com/spreadsheets/d/1zjkV9R7R_7KMItuzqzvKGwefSBRfE-ZNAx1LH55OcqY/edit?usp=sharing"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"[mainnet chain id]": {
|
||||||
|
"newMarketProposal": {
|
||||||
|
"initialDepositAmount": 0,
|
||||||
|
"delayBlocks": 0,
|
||||||
|
"newMarketsMethodology": "[URL to spreadsheet or document that explains methodology]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deployments": {
|
||||||
|
"MAINNET": {
|
||||||
|
"environments": [
|
||||||
|
"dydxprotocol-mainnet"
|
||||||
|
],
|
||||||
|
"default": "dydxprotocol-mainnet"
|
||||||
|
},
|
||||||
|
"TESTFLIGHT": {
|
||||||
|
"environments": [
|
||||||
|
"dydxprotocol-mainnet",
|
||||||
|
"dydxprotocol-testnet"
|
||||||
|
],
|
||||||
|
"default": "dydxprotocol-mainnet"
|
||||||
|
},
|
||||||
|
"TESTNET": {
|
||||||
|
"environments": [
|
||||||
|
"dydxprotocol-testnet"
|
||||||
|
],
|
||||||
|
"default": "dydxprotocol-testnet"
|
||||||
|
},
|
||||||
|
"DEV": {
|
||||||
|
"environments": [
|
||||||
|
"dydxprotocol-dev",
|
||||||
|
"dydxprotocol-dev-2",
|
||||||
|
"dydxprotocol-dev-4",
|
||||||
|
"dydxprotocol-dev-5",
|
||||||
|
"dydxprotocol-staging",
|
||||||
|
"dydxprotocol-staging-west",
|
||||||
|
"dydxprotocol-testnet",
|
||||||
|
"dydxprotocol-testnet-dydx",
|
||||||
|
"dydxprotocol-testnet-nodefleet",
|
||||||
|
"dydxprotocol-testnet-kingnodes",
|
||||||
|
"dydxprotocol-testnet-liquify",
|
||||||
|
"dydxprotocol-testnet-polkachu",
|
||||||
|
"dydxprotocol-testnet-bware"
|
||||||
|
],
|
||||||
|
"default": "dydxprotocol-testnet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"environments": {
|
||||||
|
"dydxprotocol-dev": {
|
||||||
|
"name": "v4 Dev",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydxprotocol-testnet",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4dev.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4dev.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://validator.v4dev.dydx.exchange"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.0xsquid.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
|
||||||
|
"faucet": "https://faucet.v4dev.dydx.exchange"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-dev-2": {
|
||||||
|
"name": "v4 Dev 2",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydxprotocol-testnet",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "http://dev2-indexer-apne1-lb-public-2076363889.ap-northeast-1.elb.amazonaws.com",
|
||||||
|
"socket": "ws://dev2-indexer-apne1-lb-public-2076363889.ap-northeast-1.elb.amazonaws.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"http://54.92.118.111"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.0xsquid.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-dev-4": {
|
||||||
|
"name": "v4 Dev 4",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydxprotocol-testnet",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4dev4.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4dev4.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://validator.v4dev4.dydx.exchange"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.0xsquid.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
|
||||||
|
"faucet": "https://faucet.v4dev4.dydx.exchange"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-dev-5": {
|
||||||
|
"name": "v4 Dev 5",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydxprotocol-testnet",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "http://dev5-indexer-apne1-lb-public-1721328151.ap-northeast-1.elb.amazonaws.com",
|
||||||
|
"socket": "ws://dev5-indexer-apne1-lb-public-1721328151.ap-northeast-1.elb.amazonaws.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"http://18.223.78.50"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.0xsquid.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-staging": {
|
||||||
|
"name": "v4 Staging",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydxprotocol-testnet",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4staging.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4staging.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"faucet": "https://faucet.v4staging.dydx.exchange",
|
||||||
|
"validators": [
|
||||||
|
"https://validator.v4staging.dydx.exchange"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-staging-forced-update": {
|
||||||
|
"name": "v4 Staging Forced Update",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydxprotocol-testnet",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4staging.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4staging.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"faucet": "https://faucet.v4staging.dydx.exchange",
|
||||||
|
"validators": [
|
||||||
|
"https://validator.v4staging.dydx.exchange"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
|
||||||
|
},
|
||||||
|
"apps": {
|
||||||
|
"ios": {
|
||||||
|
"minimalVersion": "1.0",
|
||||||
|
"build": 40000,
|
||||||
|
"url": "https://apps.apple.com/app/dydx/id1564787350"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-staging-west": {
|
||||||
|
"name": "v4 Staging West",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydxprotocol-testnet",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4staging.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4staging.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"faucet": "https://faucet.v4staging.dydx.exchange",
|
||||||
|
"validators": [
|
||||||
|
"https://validator-uswest1.v4staging.dydx.exchange"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-testnet": {
|
||||||
|
"name": "v4 Public Testnet",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydx-testnet-4",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://dydx-testnet-full-rpc.public.blastapi.io/",
|
||||||
|
"https://dydx-testnet-rpc.polkachu.com/",
|
||||||
|
"https://dydx-testnet.nodefleet.org",
|
||||||
|
"https://test-dydx.kingnodes.com",
|
||||||
|
"https://dydx-rpc.liquify.com/api=8878132/dydx"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
|
||||||
|
"faucet": "https://faucet.v4testnet.dydx.exchange"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-testnet-dydx": {
|
||||||
|
"name": "v4 Public Testnet/dYdX",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydx-testnet-4",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://validator.v4testnet.dydx.exchange"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
|
||||||
|
"faucet": "https://faucet.v4testnet.dydx.exchange"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-testnet-nodefleet": {
|
||||||
|
"name": "v4 Public Testnet/nodefleet",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydx-testnet-4",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://dydx-testnet.nodefleet.org"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
|
||||||
|
"faucet": "https://faucet.v4testnet.dydx.exchange"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-testnet-kingnodes": {
|
||||||
|
"name": "v4 Public Testnet/KingNodes",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydx-testnet-4",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://test-dydx.kingnodes.com"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
|
||||||
|
"faucet": "https://faucet.v4testnet.dydx.exchange"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-testnet-liquify": {
|
||||||
|
"name": "v4 Public Testnet/Liquify",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydx-testnet-4",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://dydx-rpc.liquify.com/api=8878132/dydx"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
|
||||||
|
"faucet": "https://faucet.v4testnet.dydx.exchange"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-testnet-polkachu": {
|
||||||
|
"name": "v4 Public Testnet/Polkahcu",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydx-testnet-4",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://dydx-testnet-rpc.polkachu.com/"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
|
||||||
|
"faucet": "https://faucet.v4testnet.dydx.exchange"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-testnet-bware": {
|
||||||
|
"name": "v4 Public Testnet/BWare",
|
||||||
|
"ethereumChainId": "11155111",
|
||||||
|
"dydxChainId": "dydx-testnet-4",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "dYdX-api",
|
||||||
|
"isMainNet": false,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "https://indexer.v4testnet.dydx.exchange",
|
||||||
|
"socket": "wss://indexer.v4testnet.dydx.exchange"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"https://dydx-testnet-full-rpc.public.blastapi.io/"
|
||||||
|
],
|
||||||
|
"0xsquid": "https://testnet.api.squidrouter.com",
|
||||||
|
"nobleValidator": "https://noble-testnet-rpc.polkachu.com/",
|
||||||
|
"faucet": "https://faucet.v4testnet.dydx.exchange"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": true,
|
||||||
|
"usePessimisticCollateralCheck": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dydxprotocol-mainnet": {
|
||||||
|
"name": "v4",
|
||||||
|
"ethereumChainId": "1",
|
||||||
|
"dydxChainId": "[mainnet chain id]",
|
||||||
|
"chainName": "dYdX Chain",
|
||||||
|
"chainLogo": "/dydx-chain.png",
|
||||||
|
"squidIntegratorId": "[mainnet squid integrator id]",
|
||||||
|
"isMainNet": true,
|
||||||
|
"endpoints": {
|
||||||
|
"indexers": [
|
||||||
|
{
|
||||||
|
"api": "[REST endpoint]",
|
||||||
|
"socket": "[Websocket endpoint]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validators": [
|
||||||
|
"[Validator endpoint 1",
|
||||||
|
"[Validator endpoint n]"
|
||||||
|
],
|
||||||
|
"0xsquid": "[0xSquid endpoint for mainnet]",
|
||||||
|
"nobleValidator": "[noble validator endpoint for mainnet]"
|
||||||
|
},
|
||||||
|
"featureFlags": {
|
||||||
|
"reduceOnlySupported": false,
|
||||||
|
"usePessimisticCollateralCheck": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -40,6 +40,7 @@
|
|||||||
"iosMinVersion": "0",
|
"iosMinVersion": "0",
|
||||||
"imageUrl": "",
|
"imageUrl": "",
|
||||||
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
||||||
|
"androidPackage": "io.metamask",
|
||||||
"connections": [
|
"connections": [
|
||||||
{
|
{
|
||||||
"type": "walletConnectV2",
|
"type": "walletConnectV2",
|
||||||
@ -98,6 +99,7 @@
|
|||||||
"iosMinVersion": "1.8.0",
|
"iosMinVersion": "1.8.0",
|
||||||
"imageUrl": "",
|
"imageUrl": "",
|
||||||
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
||||||
|
"androidPackage": "org.toshi",
|
||||||
"connections": [
|
"connections": [
|
||||||
{
|
{
|
||||||
"type": "walletSegue",
|
"type": "walletSegue",
|
||||||
@ -155,6 +157,7 @@
|
|||||||
"comment": "imToken",
|
"comment": "imToken",
|
||||||
"iosMinVersion": "0",
|
"iosMinVersion": "0",
|
||||||
"imageUrl": "",
|
"imageUrl": "",
|
||||||
|
"androidPackage": "im.token.app",
|
||||||
"connections": [
|
"connections": [
|
||||||
{
|
{
|
||||||
"type": "walletConnectV2",
|
"type": "walletConnectV2",
|
||||||
@ -196,7 +199,7 @@
|
|||||||
},
|
},
|
||||||
"mobile": {
|
"mobile": {
|
||||||
"native": "trust:",
|
"native": "trust:",
|
||||||
"universal": "https://link.trustwallet.com"
|
"universal": ""
|
||||||
},
|
},
|
||||||
"desktop": {
|
"desktop": {
|
||||||
"native": "",
|
"native": "",
|
||||||
@ -214,6 +217,7 @@
|
|||||||
"iosMinVersion": "0",
|
"iosMinVersion": "0",
|
||||||
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
||||||
"imageUrl": "",
|
"imageUrl": "",
|
||||||
|
"androidPackage": "com.wallet.crypto.trustapp",
|
||||||
"connections": [
|
"connections": [
|
||||||
{
|
{
|
||||||
"type": "walletConnectV2",
|
"type": "walletConnectV2",
|
||||||
@ -271,6 +275,7 @@
|
|||||||
"iosMinVersion": "0",
|
"iosMinVersion": "0",
|
||||||
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
||||||
"imageUrl": "",
|
"imageUrl": "",
|
||||||
|
"androidPackage": "io.zerion.android",
|
||||||
"connections": [
|
"connections": [
|
||||||
{
|
{
|
||||||
"type": "walletConnectV2",
|
"type": "walletConnectV2",
|
||||||
@ -327,6 +332,7 @@
|
|||||||
"comment": "TokenPocket",
|
"comment": "TokenPocket",
|
||||||
"iosMinVersion": "0",
|
"iosMinVersion": "0",
|
||||||
"imageUrl": "",
|
"imageUrl": "",
|
||||||
|
"androidPackage": "vip.mytokenpocket",
|
||||||
"connections": [
|
"connections": [
|
||||||
{
|
{
|
||||||
"type": "walletConnectV2",
|
"type": "walletConnectV2",
|
||||||
@ -383,6 +389,7 @@
|
|||||||
"comment": "Rainbow",
|
"comment": "Rainbow",
|
||||||
"iosMinVersion": "0",
|
"iosMinVersion": "0",
|
||||||
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
||||||
|
"androidPackage": "me.rainbow",
|
||||||
"backlinked": true,
|
"backlinked": true,
|
||||||
"imageUrl": "",
|
"imageUrl": "",
|
||||||
"connections": [
|
"connections": [
|
||||||
@ -442,6 +449,7 @@
|
|||||||
"comment": "1inch",
|
"comment": "1inch",
|
||||||
"iosMinVersion": "0",
|
"iosMinVersion": "0",
|
||||||
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
"encoding": "=\"#%/<>?@\\^`{|}:&",
|
||||||
|
"androidPackage": "io.oneinch.android",
|
||||||
"imageUrl": "",
|
"imageUrl": "",
|
||||||
"connections": [
|
"connections": [
|
||||||
{
|
{
|
||||||
|
|||||||
BIN
public/currencies/agix.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/currencies/bnb.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
public/currencies/bonk.png
Normal file
|
After Width: | Height: | Size: 109 KiB |
BIN
public/currencies/chz.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/currencies/dym.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/currencies/ens.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
public/currencies/fet.png
Normal file
|
After Width: | Height: | Size: 348 KiB |
BIN
public/currencies/ftm.png
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
public/currencies/gala.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
public/currencies/gmt.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
public/currencies/grt.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
public/currencies/hbar.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/currencies/imx.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
public/currencies/inj.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
public/currencies/jto.png
Normal file
|
After Width: | Height: | Size: 117 KiB |
BIN
public/currencies/jup.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
public/currencies/kava.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
public/currencies/mana.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
public/currencies/mask.png
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
public/currencies/mina.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
public/currencies/ordi.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
public/currencies/pyth.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/currencies/rndr.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
public/currencies/sand.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/currencies/strk.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/currencies/stx.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/currencies/tia.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/currencies/unavailable.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
public/currencies/woo.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/currencies/zeta.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
230
public/dots-background-2.svg
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
<svg width="254" height="77" viewBox="0 0 254 77" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Group 1258">
|
||||||
|
<g id="Ellipse 9" opacity="0.4" filter="url(#filter0_f_20300_14972)">
|
||||||
|
<ellipse cx="86.5425" cy="-3.91219" rx="116.542" ry="20.0878" fill="#7774FF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 10" opacity="0.3" filter="url(#filter1_f_20300_14972)">
|
||||||
|
<circle cx="74.5734" cy="4.63007" r="1.00507" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 12" opacity="0.3" filter="url(#filter2_f_20300_14972)">
|
||||||
|
<circle cx="82.1105" cy="7.64179" r="1.00507" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 22" opacity="0.3" filter="url(#filter3_f_20300_14972)">
|
||||||
|
<circle cx="116.785" cy="4.63007" r="1.00507" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 11" opacity="0.3" filter="url(#filter4_f_20300_14972)">
|
||||||
|
<circle cx="64.774" cy="8.90488" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 18" opacity="0.3" filter="url(#filter5_f_20300_14972)">
|
||||||
|
<circle cx="96.4322" cy="3.87363" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 20" opacity="0.3" filter="url(#filter6_f_20300_14972)">
|
||||||
|
<circle cx="76.0807" cy="14.9361" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 21" opacity="0.3" filter="url(#filter7_f_20300_14972)">
|
||||||
|
<circle cx="104.725" cy="4.87754" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 23" opacity="0.3" filter="url(#filter8_f_20300_14972)">
|
||||||
|
<circle cx="114.021" cy="7.13925" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 24" opacity="0.3" filter="url(#filter9_f_20300_14972)">
|
||||||
|
<circle cx="109.75" cy="15.4361" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 25" opacity="0.3" filter="url(#filter10_f_20300_14972)">
|
||||||
|
<circle cx="119.801" cy="12.6705" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 27" opacity="0.3" filter="url(#filter11_f_20300_14972)">
|
||||||
|
<circle cx="94.0885" cy="11.0182" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 30" opacity="0.3" filter="url(#filter12_f_20300_14972)">
|
||||||
|
<circle cx="154.475" cy="11.6666" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 29" opacity="0.3" filter="url(#filter13_f_20300_14972)">
|
||||||
|
<circle cx="146.435" cy="8.90488" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 15" opacity="0.3" filter="url(#filter14_f_20300_14972)">
|
||||||
|
<circle cx="24.0103" cy="4.44785" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 33" opacity="0.3" filter="url(#filter15_f_20300_14972)">
|
||||||
|
<circle cx="-1.05899" cy="13.6783" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 16" opacity="0.3" filter="url(#filter16_f_20300_14972)">
|
||||||
|
<circle cx="17.441" cy="16.4908" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 35" opacity="0.3" filter="url(#filter17_f_20300_14972)">
|
||||||
|
<circle cx="36.0553" cy="6.63535" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 32" opacity="0.3" filter="url(#filter18_f_20300_14972)">
|
||||||
|
<circle cx="10.8707" cy="14.2994" r="0.502536" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 13" opacity="0.3" filter="url(#filter19_f_20300_14972)">
|
||||||
|
<circle cx="55.7274" cy="9.65615" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 19" opacity="0.3" filter="url(#filter20_f_20300_14972)">
|
||||||
|
<circle cx="87.3886" cy="20.7108" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 26" opacity="0.3" filter="url(#filter21_f_20300_14972)">
|
||||||
|
<circle cx="123.82" cy="15.1874" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 36" opacity="0.3" filter="url(#filter22_f_20300_14972)">
|
||||||
|
<circle cx="134.876" cy="14.4335" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 28" opacity="0.3" filter="url(#filter23_f_20300_14972)">
|
||||||
|
<circle cx="129.6" cy="6.38662" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 14" opacity="0.3" filter="url(#filter24_f_20300_14972)">
|
||||||
|
<circle cx="41.6571" cy="14.9335" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 31" opacity="0.3" filter="url(#filter25_f_20300_14972)">
|
||||||
|
<circle cx="4.21767" cy="17.9491" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 34" opacity="0.3" filter="url(#filter26_f_20300_14972)">
|
||||||
|
<circle cx="12.2177" cy="6.88662" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
<g id="Ellipse 17" opacity="0.3" filter="url(#filter27_f_20300_14972)">
|
||||||
|
<circle cx="50.2001" cy="3.6249" r="0.753803" fill="#9A9AFF"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_f_20300_14972" x="-94" y="-88" width="361.085" height="168.176" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="32" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter1_f_20300_14972" x="72.5633" y="2.61993" width="4.01991" height="4.02186" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter2_f_20300_14972" x="80.6029" y="6.13418" width="3.01484" height="3.01679" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter3_f_20300_14972" x="115.278" y="3.12246" width="3.01484" height="3.01679" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter4_f_20300_14972" x="63.2664" y="7.39727" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter5_f_20300_14972" x="94.9246" y="2.36602" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter6_f_20300_14972" x="74.5731" y="13.4285" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter7_f_20300_14972" x="103.218" y="3.36993" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter8_f_20300_14972" x="112.513" y="5.63165" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter9_f_20300_14972" x="108.242" y="13.9285" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter10_f_20300_14972" x="118.294" y="11.1629" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter11_f_20300_14972" x="92.5809" y="9.51055" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter12_f_20300_14972" x="153.47" y="10.6615" width="2.00995" height="2.00898" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter13_f_20300_14972" x="144.928" y="7.39727" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter14_f_20300_14972" x="22.5027" y="2.94024" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter15_f_20300_14972" x="-2.56659" y="12.1707" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter16_f_20300_14972" x="15.9334" y="14.9832" width="3.01502" height="3.01405" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter17_f_20300_14972" x="35.0502" y="5.63028" width="2.00995" height="2.00898" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter18_f_20300_14972" x="9.86563" y="13.2943" width="2.00995" height="2.00898" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.251268" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter19_f_20300_14972" x="53.9686" y="7.89727" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter20_f_20300_14972" x="85.6297" y="18.952" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter21_f_20300_14972" x="122.061" y="13.4285" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter22_f_20300_14972" x="133.117" y="12.6746" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter23_f_20300_14972" x="127.842" y="4.62774" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter24_f_20300_14972" x="39.8982" y="13.1746" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter25_f_20300_14972" x="2.4588" y="16.1902" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter26_f_20300_14972" x="10.4588" y="5.12774" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter27_f_20300_14972" x="48.4412" y="1.86602" width="3.51795" height="3.51795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.502536" result="effect1_foregroundBlur_20300_14972"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 15 KiB |
1
public/dots-background.svg
Normal file
|
After Width: | Height: | Size: 300 KiB |
BIN
public/exchanges/coinbase.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
1
public/libs/amplitude-analytics-browser-2.0.0-min.js
vendored
Normal file
1
public/rewards-stars.svg
Normal file
|
After Width: | Height: | Size: 481 KiB |
15
public/smartbanner.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<!-- Smartbanner: Configure the mobile app -->
|
||||||
|
<meta name="smartbanner:title" content="SMARTBANNER_APP_NAME">
|
||||||
|
<meta name="smartbanner:author" content="SMARTBANNER_ORG_NAME">
|
||||||
|
<meta name="smartbanner:icon-apple" content="SMARTBANNER_ICON_URL">
|
||||||
|
<meta name="smartbanner:icon-google" content="SMARTBANNER_ICON_URL">
|
||||||
|
<!-- Smartbanner: The rest of the configurations can be kept as is -->
|
||||||
|
<meta name="smartbanner:price" content="FREE">
|
||||||
|
<meta name="smartbanner:price-suffix-apple" content=" - On the App Store">
|
||||||
|
<meta name="smartbanner:price-suffix-google" content=" - In Google Play">
|
||||||
|
<meta name="smartbanner:button" content="VIEW">
|
||||||
|
<meta name="smartbanner:close-label" content="Close">
|
||||||
|
<meta name="smartbanner:exclude-user-agent-regex" content="^.*(Windows NT|Intel Mac OS X).*$">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/smartbanner.js@1.22.0/dist/smartbanner.min.js"></script>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/smartbanner.js@1.22.0/dist/smartbanner.min.css" rel="stylesheet">
|
||||||
|
<!-- Smartbanner: End configuration -->
|
||||||
BIN
public/third-party/keplr.png
vendored
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/third-party/stride.png
vendored
Normal file
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 817 B After Width: | Height: | Size: 297 B |
BIN
public/wallets/okx-wallet.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
52
scripts/README.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
## App Integrations
|
||||||
|
### Amplitude
|
||||||
|
Analytics service used to collect data to help the dYdX Product team make informed product decisions.
|
||||||
|
|
||||||
|
<b>To use with dydxprotocol/v4-web:</b>
|
||||||
|
1. Amplitude account with API key.
|
||||||
|
2. Add API key in Github > Secrets and Variables > Actions as `AMPLITUDE_API_KEY`
|
||||||
|
3. In your deploy scripts add `pnpm run build:inject-amplitude` after your pnpm build / vite build command.
|
||||||
|
|
||||||
|
### Bugsnag
|
||||||
|
Error handling service used to collect handled/unhandled errors within the app. The information collected is used to help debug and alert the engineering team of crashes/unhandled errors within the app to improve stability.
|
||||||
|
|
||||||
|
<b>To use with dydxprotocol/v4-web:</b>
|
||||||
|
1. Bugsnag account with API key.
|
||||||
|
2. Add API key in Github > Secrets and Variables > Actions as `BUGSNAG_API_KEY`
|
||||||
|
3. In your deploy scripts add `pnpm run build:inject-bugsnag` after your pnpm build / vite build command.
|
||||||
|
4. If you are using with the Amplitude deployment scripts, your build command may look like the following: `pnpm build && pnpm run build:inject-amplitude && pnpm run build:inject-bugsnag`
|
||||||
|
|
||||||
|
### StatusPage
|
||||||
|
Service used to inform users of any status updates to our platform. These status updates are manually set and updated by the On Call engineers.
|
||||||
|
|
||||||
|
<b>To use with dydxprotocol/v4-web:</b>
|
||||||
|
1. StatusPage account and script URI
|
||||||
|
2. Add API key in Github > Secrets and Variables > Actions as `STATUS_PAGE_SCRIPT_URI`
|
||||||
|
3. In your deploy scripts add `pnpm run build:inject-statuspage` after your pnpm build / vite build command.
|
||||||
|
4. If you are using with the Amplitude deployment scripts, your build command may look like the following: `pnpm build && pnpm run build:inject-amplitude && pnpm run build:inject-statuspage`
|
||||||
|
|
||||||
|
### Intercom
|
||||||
|
Service used for live customer support (chat/inbox) as well as home for Help Articles.
|
||||||
|
|
||||||
|
<b>To use with dydxprotocol/v4-web:</b>
|
||||||
|
1. Create Intercom account
|
||||||
|
2. In Intercom UI
|
||||||
|
Getting started > Set up Messenger > will give you your API Key on Step 2
|
||||||
|
Customize Intercom Messenger by adding logo and brand colors
|
||||||
|
3. Add API key in Github > Secrets and Variables > Actions as `INTERCOM_APP_ID`
|
||||||
|
4. In your deploy scripts add `pnpm run build:inject-intercom` after your pnpm build / vite build command.
|
||||||
|
5. If you are using with the Amplitude deployment scripts, your build command may look like the following: `pnpm build && pnpm run build:inject-amplitude && pnpm run build:inject-intercom`
|
||||||
|
|
||||||
|
### Smartbanner
|
||||||
|
Smartbanner to show download links to iOS and/or Android native apps on mobile devices.
|
||||||
|
|
||||||
|
<b>To use with dydxprotocol/v4-web:</b>
|
||||||
|
1. iOS app App Store link or Android app Google Play link.
|
||||||
|
2. Add configurations in Github > Secrets and Variables > Actions as
|
||||||
|
`SMARTBANNER_APP_NAME` for app name
|
||||||
|
`SMARTBANNER_ORG_NAME` for organization name
|
||||||
|
`SMARTBANNER_ICON_URL` for icon image
|
||||||
|
`SMARTBANNER_APPSTORE_URL` for iOS App Store link
|
||||||
|
`SMARTBANNER_GOOGLEPLAY_URL` for Android Google Play link
|
||||||
|
3. In your deploy scripts add `pnpm run build:inject-smartbanner` after your pnpm build / vite build command.
|
||||||
|
4. If you are using with the Amplitude deployment scripts, your build command may look like the following: `pnpm build && pnpm run build:inject-smartbanner`
|
||||||
@ -3,23 +3,50 @@ import path from 'path';
|
|||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
const AMPLITUDE_API_KEY = process.env.AMPLITUDE_API_KEY;
|
const AMPLITUDE_API_KEY = process.env.AMPLITUDE_API_KEY;
|
||||||
|
const AMPLITUDE_SERVER_URL = process.env.AMPLITUDE_SERVER_URL;
|
||||||
|
|
||||||
const currentPath = fileURLToPath(import.meta.url);
|
const currentPath = fileURLToPath(import.meta.url);
|
||||||
const projectRoot = path.dirname(currentPath);
|
const projectRoot = path.dirname(currentPath);
|
||||||
const htmlFilePath = path.resolve(projectRoot, '../dist/index.html');
|
const htmlFilePath = path.resolve(projectRoot, '../dist/index.html');
|
||||||
|
|
||||||
if(AMPLITUDE_API_KEY){
|
if (AMPLITUDE_API_KEY) {
|
||||||
try {
|
try {
|
||||||
const html = await fs.readFile(htmlFilePath, 'utf-8');
|
const html = await fs.readFile(htmlFilePath, 'utf-8');
|
||||||
|
|
||||||
const amplitudeCdnScript = `<script type="text/javascript">
|
const amplitudeCdnScript = `<script type="text/javascript">
|
||||||
!function(){"use strict";!function(e,t){var n=e.amplitude||{_q:[],_iq:{}};if(n.invoked)e.console&&console.error&&console.error("Amplitude snippet has been loaded.");else{var r=function(e,t){e.prototype[t]=function(){return this._q.push({name:t,args:Array.prototype.slice.call(arguments,0)}),this}},s=function(e,t,n){return function(r){e._q.push({name:t,args:Array.prototype.slice.call(n,0),resolve:r})}},o=function(e,t,n){e[t]=function(){if(n)return{promise:new Promise(s(e,t,Array.prototype.slice.call(arguments)))}}},i=function(e){for(var t=0;t<m.length;t++)o(e,m[t],!1);for(var n=0;n<g.length;n++)o(e,g[n],!0)};n.invoked=!0;var u=t.createElement("script");u.type="text/javascript",u.integrity="sha384-x0ik2D45ZDEEEpYpEuDpmj05fY91P7EOZkgdKmq4dKL/ZAVcufJ+nULFtGn0HIZE",u.crossOrigin="anonymous",u.async=!0,u.src="https://cdn.amplitude.com/libs/analytics-browser-2.0.0-min.js.gz",u.onload=function(){e.amplitude.runQueuedFunctions||console.log("[Amplitude] Error: could not load SDK")};var a=t.getElementsByTagName("script")[0];a.parentNode.insertBefore(u,a);for(var c=function(){return this._q=[],this},p=["add","append","clearAll","prepend","set","setOnce","unset","preInsert","postInsert","remove","getUserProperties"],l=0;l<p.length;l++)r(c,p[l]);n.Identify=c;for(var d=function(){return this._q=[],this},f=["getEventProperties","setProductId","setQuantity","setPrice","setRevenue","setRevenueType","setEventProperties"],v=0;v<f.length;v++)r(d,f[v]);n.Revenue=d;var m=["getDeviceId","setDeviceId","getSessionId","setSessionId","getUserId","setUserId","setOptOut","setTransport","reset","extendSession"],g=["init","add","remove","track","logEvent","identify","groupIdentify","setGroup","revenue","flush"];i(n),n.createInstance=function(e){return n._iq[e]={_q:[]},i(n._iq[e]),n._iq[e]},e.amplitude=n}}(window,document)}();
|
!function(){"use strict";!function(e,t){var n=e.amplitude||{_q:[],_iq:{}};if(n.invoked)e.console&&console.error&&console.error("Amplitude snippet has been loaded.");else{var r=function(e,t){e.prototype[t]=function(){return this._q.push({name:t,args:Array.prototype.slice.call(arguments,0)}),this}},s=function(e,t,n){return function(r){e._q.push({name:t,args:Array.prototype.slice.call(n,0),resolve:r})}},o=function(e,t,n){e[t]=function(){if(n)return{promise:new Promise(s(e,t,Array.prototype.slice.call(arguments)))}}},i=function(e){for(var t=0;t<m.length;t++)o(e,m[t],!1);for(var n=0;n<g.length;n++)o(e,g[n],!0)};n.invoked=!0;var u=t.createElement("script");u.type="text/javascript",u.integrity="sha384-BVo5ZjsjH373rWbcjz9Qjb2L6BgLwLADcZtZZPu3nMl8+7LPDhi1NcUEf0Ate41Y",u.crossOrigin="anonymous",u.async=!0,u.src="/libs/amplitude-analytics-browser-2.0.0-min.js",u.onload=function(){e.amplitude.runQueuedFunctions||console.log("[Amplitude] Error: could not load SDK")};var a=t.getElementsByTagName("script")[0];a.parentNode.insertBefore(u,a);for(var c=function(){return this._q=[],this},p=["add","append","clearAll","prepend","set","setOnce","unset","preInsert","postInsert","remove","getUserProperties"],l=0;l<p.length;l++)r(c,p[l]);n.Identify=c;for(var d=function(){return this._q=[],this},f=["getEventProperties","setProductId","setQuantity","setPrice","setRevenue","setRevenueType","setEventProperties"],v=0;v<f.length;v++)r(d,f[v]);n.Revenue=d;var m=["getDeviceId","setDeviceId","getSessionId","setSessionId","getUserId","setUserId","setOptOut","setTransport","reset","extendSession"],g=["init","add","remove","track","logEvent","identify","groupIdentify","setGroup","revenue","flush"];i(n),n.createInstance=function(e){return n._iq[e]={_q:[]},i(n._iq[e]),n._iq[e]},e.amplitude=n}}(window,document)}();
|
||||||
</script>
|
</script>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const amplitudeListenerScript = `<script type="module">
|
const amplitudeListenerScript = `<script type="module">
|
||||||
!function(){var e="${AMPLITUDE_API_KEY}";e&&(globalThis.amplitude.init(e),globalThis.amplitude.setOptOut(!1),globalThis.addEventListener("dydx:track",function(e){var t=e.detail.eventType,d=e.detail.eventData;globalThis.amplitude.track(t,d)}),globalThis.addEventListener("dydx:identify",function(e){var t=e.detail.property,d=e.detail.propertyValue;if("walletAddress"===t)globalThis.amplitude.setUserId(d);else{var i=new globalThis.amplitude.Identify;i.set(t,d),globalThis.amplitude.identify(i)}}),console.log("Amplitude enabled."))}();
|
!(function () {
|
||||||
</script>`;
|
var e = "${AMPLITUDE_API_KEY}";
|
||||||
|
e &&
|
||||||
|
(globalThis.amplitude.init(e${
|
||||||
|
AMPLITUDE_SERVER_URL
|
||||||
|
? `, undefined, {
|
||||||
|
serverUrl: "${AMPLITUDE_SERVER_URL}"
|
||||||
|
}`
|
||||||
|
: ''
|
||||||
|
}),
|
||||||
|
globalThis.amplitude.setOptOut(!1),
|
||||||
|
globalThis.addEventListener("dydx:track", function (e) {
|
||||||
|
var t = e.detail.eventType,
|
||||||
|
d = e.detail.eventData;
|
||||||
|
globalThis.amplitude.track(t, d);
|
||||||
|
}),
|
||||||
|
globalThis.addEventListener("dydx:identify", function (e) {
|
||||||
|
var t = e.detail.property,
|
||||||
|
d = e.detail.propertyValue;
|
||||||
|
if ("walletAddress" === t) globalThis.amplitude.setUserId(d);
|
||||||
|
else {
|
||||||
|
var i = new globalThis.amplitude.Identify();
|
||||||
|
i.set(t, d), globalThis.amplitude.identify(i);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
console.log("Amplitude enabled."));
|
||||||
|
})();
|
||||||
|
</script>`;
|
||||||
|
|
||||||
const injectedHtml = html.replace(
|
const injectedHtml = html.replace(
|
||||||
'<div id="root"></div>',
|
'<div id="root"></div>',
|
||||||
|
|||||||
60
scripts/inject-smartbanner.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
import path from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
const SMARTBANNER_APP_NAME = process.env.SMARTBANNER_APP_NAME;
|
||||||
|
const SMARTBANNER_ORG_NAME = process.env.SMARTBANNER_ORG_NAME;
|
||||||
|
const SMARTBANNER_ICON_URL = process.env.SMARTBANNER_ICON_URL;
|
||||||
|
const SMARTBANNER_APPSTORE_URL = process.env.SMARTBANNER_APPSTORE_URL;
|
||||||
|
const SMARTBANNER_GOOGLEPLAY_URL = process.env.SMARTBANNER_GOOGLEPLAY_URL;
|
||||||
|
|
||||||
|
const currentPath = fileURLToPath(import.meta.url);
|
||||||
|
const projectRoot = path.dirname(currentPath);
|
||||||
|
const htmlFilePath = path.resolve(projectRoot, '../dist/index.html');
|
||||||
|
const smartbannerFilePath = path.resolve(projectRoot, '../dist/smartbanner.html');
|
||||||
|
|
||||||
|
if (
|
||||||
|
SMARTBANNER_APP_NAME &&
|
||||||
|
SMARTBANNER_ORG_NAME &&
|
||||||
|
SMARTBANNER_ICON_URL &&
|
||||||
|
(SMARTBANNER_APPSTORE_URL || SMARTBANNER_GOOGLEPLAY_URL)
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const html = await fs.readFile(htmlFilePath, 'utf-8');
|
||||||
|
let smartbanner = await fs.readFile(smartbannerFilePath, 'utf-8');
|
||||||
|
smartbanner = smartbanner
|
||||||
|
.replace('SMARTBANNER_APP_NAME', SMARTBANNER_APP_NAME)
|
||||||
|
.replace('SMARTBANNER_ORG_NAME', SMARTBANNER_ORG_NAME)
|
||||||
|
.replace('SMARTBANNER_ICON_URL', SMARTBANNER_ICON_URL)
|
||||||
|
.replace('SMARTBANNER_ICON_URL', SMARTBANNER_ICON_URL);
|
||||||
|
|
||||||
|
/* hardcoded injection depending on whether the app is available on App Store and/or Google Play */
|
||||||
|
|
||||||
|
if (SMARTBANNER_APPSTORE_URL) {
|
||||||
|
smartbanner = `\t<meta name="smartbanner:button-url-apple" content="${SMARTBANNER_APPSTORE_URL}">\n` + smartbanner;
|
||||||
|
}
|
||||||
|
if (SMARTBANNER_GOOGLEPLAY_URL) {
|
||||||
|
smartbanner = `\t<meta name="smartbanner:button-url-google" content="${SMARTBANNER_GOOGLEPLAY_URL}">\n` + smartbanner;
|
||||||
|
}
|
||||||
|
if (SMARTBANNER_APPSTORE_URL) {
|
||||||
|
if (SMARTBANNER_GOOGLEPLAY_URL) {
|
||||||
|
smartbanner = `\t<meta name="smartbanner:enabled-platforms" content="android,ios">\n` + smartbanner;
|
||||||
|
} else {
|
||||||
|
smartbanner = `\t<meta name="smartbanner:enabled-platforms" content="ios">\n` + smartbanner;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (SMARTBANNER_GOOGLEPLAY_URL) {
|
||||||
|
smartbanner = `\t<meta name="smartbanner:enabled-platforms" content="android">\n` + smartbanner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const injectedHtml = html.replace('</head>', `${smartbanner}\n</head>`);
|
||||||
|
|
||||||
|
await fs.writeFile(htmlFilePath, injectedHtml, 'utf-8');
|
||||||
|
|
||||||
|
console.log('Smartbanner scripts successfully injected.');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error injecting Smartbanner scripts:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
123
src/App.tsx
@ -1,11 +1,11 @@
|
|||||||
import { Suspense } from 'react';
|
import { lazy, Suspense, useMemo } from 'react';
|
||||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
import { Navigate, Route, Routes, useLocation } from 'react-router-dom';
|
||||||
import styled, { AnyStyledComponent, css } from 'styled-components';
|
import styled, { AnyStyledComponent, css } from 'styled-components';
|
||||||
import { WagmiConfig } from 'wagmi';
|
import { WagmiConfig } from 'wagmi';
|
||||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||||
import { GrazProvider } from 'graz';
|
import { GrazProvider } from 'graz';
|
||||||
|
|
||||||
import { AppRoute, DEFAULT_TRADE_ROUTE } from '@/constants/routes';
|
import { AppRoute, DEFAULT_TRADE_ROUTE, MarketsRoute } from '@/constants/routes';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useBreakpoints,
|
useBreakpoints,
|
||||||
@ -16,25 +16,17 @@ import {
|
|||||||
} from '@/hooks';
|
} from '@/hooks';
|
||||||
import { DydxProvider } from '@/hooks/useDydxClient';
|
import { DydxProvider } from '@/hooks/useDydxClient';
|
||||||
import { AccountsProvider } from '@/hooks/useAccounts';
|
import { AccountsProvider } from '@/hooks/useAccounts';
|
||||||
|
import { AppThemeAndColorModeProvider } from '@/hooks/useAppThemeAndColorMode';
|
||||||
import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
|
import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
|
||||||
import { LocaleProvider } from '@/hooks/useLocaleSeparators';
|
import { LocaleProvider } from '@/hooks/useLocaleSeparators';
|
||||||
import { NotificationsProvider } from '@/hooks/useNotifications';
|
import { NotificationsProvider } from '@/hooks/useNotifications';
|
||||||
import { LocalNotificationsProvider } from '@/hooks/useLocalNotifications';
|
import { LocalNotificationsProvider } from '@/hooks/useLocalNotifications';
|
||||||
|
import { PotentialMarketsProvider } from '@/hooks/usePotentialMarkets';
|
||||||
import { RestrictionProvider } from '@/hooks/useRestrictions';
|
import { RestrictionProvider } from '@/hooks/useRestrictions';
|
||||||
import { SubaccountProvider } from '@/hooks/useSubaccount';
|
import { SubaccountProvider } from '@/hooks/useSubaccount';
|
||||||
import { SquidProvider } from '@/hooks/useSquid';
|
|
||||||
|
|
||||||
import { GuardedMobileRoute } from '@/components/GuardedMobileRoute';
|
import { GuardedMobileRoute } from '@/components/GuardedMobileRoute';
|
||||||
|
import { LoadingSpace } from '@/components/Loading/LoadingSpinner';
|
||||||
import MarketsPage from '@/pages/markets/Markets';
|
|
||||||
import PortfolioPage from '@/pages/portfolio/Portfolio';
|
|
||||||
import { AlertsPage } from '@/pages/AlertsPage';
|
|
||||||
import ProfilePage from '@/pages/Profile';
|
|
||||||
import { SettingsPage } from '@/pages/settings/Settings';
|
|
||||||
import TradePage from '@/pages/trade/Trade';
|
|
||||||
import { RewardsPage } from '@/pages/rewards/RewardsPage';
|
|
||||||
import { TermsOfUsePage } from '@/pages/TermsOfUsePage';
|
|
||||||
import { PrivacyPolicyPage } from '@/pages/PrivacyPolicyPage';
|
|
||||||
|
|
||||||
import { HeaderDesktop } from '@/layout/Header/HeaderDesktop';
|
import { HeaderDesktop } from '@/layout/Header/HeaderDesktop';
|
||||||
import { FooterDesktop } from '@/layout/Footer/FooterDesktop';
|
import { FooterDesktop } from '@/layout/Footer/FooterDesktop';
|
||||||
@ -43,15 +35,28 @@ import { NotificationsToastArea } from '@/layout/NotificationsToastArea';
|
|||||||
import { DialogManager } from '@/layout/DialogManager';
|
import { DialogManager } from '@/layout/DialogManager';
|
||||||
import { GlobalCommandDialog } from '@/views/dialogs/GlobalCommandDialog';
|
import { GlobalCommandDialog } from '@/views/dialogs/GlobalCommandDialog';
|
||||||
|
|
||||||
|
import { parseLocationHash } from '@/lib/urlUtils';
|
||||||
import { config } from '@/lib/wagmi';
|
import { config } from '@/lib/wagmi';
|
||||||
|
|
||||||
import { breakpoints } from '@/styles';
|
import { breakpoints } from '@/styles';
|
||||||
|
import { GlobalStyle } from '@/styles/globalStyle';
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
import '@/styles/constants.css';
|
import '@/styles/constants.css';
|
||||||
import '@/styles/fonts.css';
|
import '@/styles/fonts.css';
|
||||||
import '@/styles/web3modal.css';
|
import '@/styles/web3modal.css';
|
||||||
|
|
||||||
|
const NewMarket = lazy(() => import('@/pages/markets/NewMarket'));
|
||||||
|
const MarketsPage = lazy(() => import('@/pages/markets/Markets'));
|
||||||
|
const PortfolioPage = lazy(() => import('@/pages/portfolio/Portfolio'));
|
||||||
|
const AlertsPage = lazy(() => import('@/pages/AlertsPage'));
|
||||||
|
const ProfilePage = lazy(() => import('@/pages/Profile'));
|
||||||
|
const SettingsPage = lazy(() => import('@/pages/settings/Settings'));
|
||||||
|
const TradePage = lazy(() => import('@/pages/trade/Trade'));
|
||||||
|
const TermsOfUsePage = lazy(() => import('@/pages/TermsOfUsePage'));
|
||||||
|
const PrivacyPolicyPage = lazy(() => import('@/pages/PrivacyPolicyPage'));
|
||||||
|
const TokenPage = lazy(() => import('@/pages/token/Token'));
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
const Content = () => {
|
const Content = () => {
|
||||||
@ -64,51 +69,67 @@ const Content = () => {
|
|||||||
const isShowingHeader = isNotTablet;
|
const isShowingHeader = isNotTablet;
|
||||||
const isShowingFooter = useShouldShowFooter();
|
const isShowingFooter = useShouldShowFooter();
|
||||||
const { chainTokenLabel } = useTokenConfigs();
|
const { chainTokenLabel } = useTokenConfigs();
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
const pathFromHash = useMemo(() => {
|
||||||
|
if (location.hash === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return parseLocationHash(location.hash);
|
||||||
|
}, [location.hash]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
|
<>
|
||||||
{isNotTablet && <HeaderDesktop />}
|
<GlobalStyle />
|
||||||
|
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
|
||||||
|
{isNotTablet && <HeaderDesktop />}
|
||||||
|
|
||||||
<Styled.Main>
|
<Styled.Main>
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={<LoadingSpace id="main" />}>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path={AppRoute.Trade}>
|
<Route path={AppRoute.Trade}>
|
||||||
<Route path=":market" element={<TradePage />} />
|
<Route path=":market" element={<TradePage />} />
|
||||||
<Route path={AppRoute.Trade} element={<TradePage />} />
|
<Route path={AppRoute.Trade} element={<TradePage />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path={AppRoute.Markets} element={<MarketsPage />} />
|
<Route path={AppRoute.Markets}>
|
||||||
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
|
<Route path={MarketsRoute.New} element={<NewMarket />} />
|
||||||
{isTablet && (
|
<Route path={AppRoute.Markets} element={<MarketsPage />} />
|
||||||
<>
|
</Route>
|
||||||
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
<Route path={`/${chainTokenLabel}/*`} element={<TokenPage />} />
|
||||||
<Route path={AppRoute.Profile} element={<ProfilePage />} />
|
{isTablet && (
|
||||||
<Route path={`${AppRoute.Settings}/*`} element={<SettingsPage />} />
|
<>
|
||||||
</>
|
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
||||||
)}
|
<Route path={AppRoute.Profile} element={<ProfilePage />} />
|
||||||
|
<Route path={`${AppRoute.Settings}/*`} element={<SettingsPage />} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<Route element={<GuardedMobileRoute />}>
|
<Route element={<GuardedMobileRoute />}>
|
||||||
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
|
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
|
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
|
||||||
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
|
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
|
||||||
|
<Route
|
||||||
|
path="*"
|
||||||
|
element={<Navigate to={pathFromHash || DEFAULT_TRADE_ROUTE} replace />}
|
||||||
|
/>
|
||||||
|
</Routes>
|
||||||
|
</Suspense>
|
||||||
|
</Styled.Main>
|
||||||
|
|
||||||
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
|
{isTablet ? <FooterMobile /> : <FooterDesktop />}
|
||||||
</Routes>
|
|
||||||
</Suspense>
|
|
||||||
</Styled.Main>
|
|
||||||
|
|
||||||
{isTablet ? <FooterMobile /> : <FooterDesktop />}
|
<Styled.NotificationsToastArea />
|
||||||
|
|
||||||
<Styled.NotificationsToastArea />
|
<Styled.DialogArea ref={setDialogArea}>
|
||||||
|
<DialogManager />
|
||||||
|
</Styled.DialogArea>
|
||||||
|
|
||||||
<Styled.DialogArea ref={setDialogArea}>
|
<GlobalCommandDialog />
|
||||||
<DialogManager />
|
</Styled.Content>
|
||||||
</Styled.DialogArea>
|
</>
|
||||||
|
|
||||||
<GlobalCommandDialog />
|
|
||||||
</Styled.Content>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -128,10 +149,11 @@ const providers = [
|
|||||||
wrapProvider(DydxProvider),
|
wrapProvider(DydxProvider),
|
||||||
wrapProvider(AccountsProvider),
|
wrapProvider(AccountsProvider),
|
||||||
wrapProvider(SubaccountProvider),
|
wrapProvider(SubaccountProvider),
|
||||||
wrapProvider(SquidProvider),
|
|
||||||
wrapProvider(LocalNotificationsProvider),
|
wrapProvider(LocalNotificationsProvider),
|
||||||
wrapProvider(NotificationsProvider),
|
wrapProvider(NotificationsProvider),
|
||||||
wrapProvider(DialogAreaProvider),
|
wrapProvider(DialogAreaProvider),
|
||||||
|
wrapProvider(PotentialMarketsProvider),
|
||||||
|
wrapProvider(AppThemeAndColorModeProvider),
|
||||||
];
|
];
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
@ -196,6 +218,7 @@ Styled.Content = styled.div<{ isShowingHeader: boolean; isShowingFooter: boolean
|
|||||||
|
|
||||||
Styled.Main = styled.main`
|
Styled.Main = styled.main`
|
||||||
${layoutMixins.contentSectionAttached}
|
${layoutMixins.contentSectionAttached}
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
grid-area: Main;
|
grid-area: Main;
|
||||||
|
|
||||||
|
|||||||
390
src/abi/erc20_usdt.json
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "name",
|
||||||
|
"outputs": [{ "name": "", "type": "string" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [{ "name": "_upgradedAddress", "type": "address" }],
|
||||||
|
"name": "deprecate",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{ "name": "_spender", "type": "address" },
|
||||||
|
{ "name": "_value", "type": "uint256" }
|
||||||
|
],
|
||||||
|
"name": "approve",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "deprecated",
|
||||||
|
"outputs": [{ "name": "", "type": "bool" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [{ "name": "_evilUser", "type": "address" }],
|
||||||
|
"name": "addBlackList",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "totalSupply",
|
||||||
|
"outputs": [{ "name": "", "type": "uint256" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{ "name": "_from", "type": "address" },
|
||||||
|
{ "name": "_to", "type": "address" },
|
||||||
|
{ "name": "_value", "type": "uint256" }
|
||||||
|
],
|
||||||
|
"name": "transferFrom",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "upgradedAddress",
|
||||||
|
"outputs": [{ "name": "", "type": "address" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [{ "name": "", "type": "address" }],
|
||||||
|
"name": "balances",
|
||||||
|
"outputs": [{ "name": "", "type": "uint256" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "decimals",
|
||||||
|
"outputs": [{ "name": "", "type": "uint256" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "maximumFee",
|
||||||
|
"outputs": [{ "name": "", "type": "uint256" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "_totalSupply",
|
||||||
|
"outputs": [{ "name": "", "type": "uint256" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "unpause",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [{ "name": "_maker", "type": "address" }],
|
||||||
|
"name": "getBlackListStatus",
|
||||||
|
"outputs": [{ "name": "", "type": "bool" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{ "name": "", "type": "address" },
|
||||||
|
{ "name": "", "type": "address" }
|
||||||
|
],
|
||||||
|
"name": "allowed",
|
||||||
|
"outputs": [{ "name": "", "type": "uint256" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "paused",
|
||||||
|
"outputs": [{ "name": "", "type": "bool" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [{ "name": "who", "type": "address" }],
|
||||||
|
"name": "balanceOf",
|
||||||
|
"outputs": [{ "name": "", "type": "uint256" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "pause",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getOwner",
|
||||||
|
"outputs": [{ "name": "", "type": "address" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "owner",
|
||||||
|
"outputs": [{ "name": "", "type": "address" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "symbol",
|
||||||
|
"outputs": [{ "name": "", "type": "string" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{ "name": "_to", "type": "address" },
|
||||||
|
{ "name": "_value", "type": "uint256" }
|
||||||
|
],
|
||||||
|
"name": "transfer",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{ "name": "newBasisPoints", "type": "uint256" },
|
||||||
|
{ "name": "newMaxFee", "type": "uint256" }
|
||||||
|
],
|
||||||
|
"name": "setParams",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [{ "name": "amount", "type": "uint256" }],
|
||||||
|
"name": "issue",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [{ "name": "amount", "type": "uint256" }],
|
||||||
|
"name": "redeem",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{ "name": "_owner", "type": "address" },
|
||||||
|
{ "name": "_spender", "type": "address" }
|
||||||
|
],
|
||||||
|
"name": "allowance",
|
||||||
|
"outputs": [{ "name": "remaining", "type": "uint256" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "basisPointsRate",
|
||||||
|
"outputs": [{ "name": "", "type": "uint256" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [{ "name": "", "type": "address" }],
|
||||||
|
"name": "isBlackListed",
|
||||||
|
"outputs": [{ "name": "", "type": "bool" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [{ "name": "_clearedUser", "type": "address" }],
|
||||||
|
"name": "removeBlackList",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "MAX_UINT",
|
||||||
|
"outputs": [{ "name": "", "type": "uint256" }],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [{ "name": "newOwner", "type": "address" }],
|
||||||
|
"name": "transferOwnership",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [{ "name": "_blackListedUser", "type": "address" }],
|
||||||
|
"name": "destroyBlackFunds",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{ "name": "_initialSupply", "type": "uint256" },
|
||||||
|
{ "name": "_name", "type": "string" },
|
||||||
|
{ "name": "_symbol", "type": "string" },
|
||||||
|
{ "name": "_decimals", "type": "uint256" }
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "constructor"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [{ "indexed": false, "name": "amount", "type": "uint256" }],
|
||||||
|
"name": "Issue",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [{ "indexed": false, "name": "amount", "type": "uint256" }],
|
||||||
|
"name": "Redeem",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [{ "indexed": false, "name": "newAddress", "type": "address" }],
|
||||||
|
"name": "Deprecate",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{ "indexed": false, "name": "feeBasisPoints", "type": "uint256" },
|
||||||
|
{ "indexed": false, "name": "maxFee", "type": "uint256" }
|
||||||
|
],
|
||||||
|
"name": "Params",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{ "indexed": false, "name": "_blackListedUser", "type": "address" },
|
||||||
|
{ "indexed": false, "name": "_balance", "type": "uint256" }
|
||||||
|
],
|
||||||
|
"name": "DestroyedBlackFunds",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [{ "indexed": false, "name": "_user", "type": "address" }],
|
||||||
|
"name": "AddedBlackList",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [{ "indexed": false, "name": "_user", "type": "address" }],
|
||||||
|
"name": "RemovedBlackList",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{ "indexed": true, "name": "owner", "type": "address" },
|
||||||
|
{ "indexed": true, "name": "spender", "type": "address" },
|
||||||
|
{ "indexed": false, "name": "value", "type": "uint256" }
|
||||||
|
],
|
||||||
|
"name": "Approval",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{ "indexed": true, "name": "from", "type": "address" },
|
||||||
|
{ "indexed": true, "name": "to", "type": "address" },
|
||||||
|
{ "indexed": false, "name": "value", "type": "uint256" }
|
||||||
|
],
|
||||||
|
"name": "Transfer",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{ "anonymous": false, "inputs": [], "name": "Pause", "type": "event" },
|
||||||
|
{ "anonymous": false, "inputs": [], "name": "Unpause", "type": "event" }
|
||||||
|
]
|
||||||
26
src/components/Accordion.stories.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import type { Story } from '@ladle/react';
|
||||||
|
|
||||||
|
import { Accordion as AccordionComponent, AccordionProps } from '@/components/Accordion';
|
||||||
|
|
||||||
|
import { StoryWrapper } from '.ladle/components';
|
||||||
|
|
||||||
|
export const Accordion: Story<AccordionProps> = (args) => {
|
||||||
|
return (
|
||||||
|
<StoryWrapper>
|
||||||
|
<AccordionComponent {...args} />
|
||||||
|
</StoryWrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Accordion.args = {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
header: 'Question 1?',
|
||||||
|
content: 'Answer 1.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Question 2?',
|
||||||
|
content: 'Answer 2.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
129
src/components/Accordion.tsx
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import styled, { keyframes, type AnyStyledComponent } from 'styled-components';
|
||||||
|
|
||||||
|
import { Root, Item, Header, Trigger, Content } from '@radix-ui/react-accordion';
|
||||||
|
|
||||||
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
import { breakpoints } from '@/styles';
|
||||||
|
|
||||||
|
import { PlusIcon } from '@/icons';
|
||||||
|
|
||||||
|
export type AccordionItem = {
|
||||||
|
header: React.ReactNode;
|
||||||
|
content: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AccordionProps = {
|
||||||
|
items: AccordionItem[];
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Accordion = ({ items, className }: AccordionProps) => (
|
||||||
|
<Styled.Root className={className} type="single" collapsible>
|
||||||
|
{items.map(({ header, content }, idx) => (
|
||||||
|
<Styled.Item key={idx} value={idx.toString()}>
|
||||||
|
<Header>
|
||||||
|
<Styled.Trigger>
|
||||||
|
{header}
|
||||||
|
<Styled.Icon>
|
||||||
|
<PlusIcon />
|
||||||
|
</Styled.Icon>
|
||||||
|
</Styled.Trigger>
|
||||||
|
</Header>
|
||||||
|
<Styled.Content>{content}</Styled.Content>
|
||||||
|
</Styled.Item>
|
||||||
|
))}
|
||||||
|
</Styled.Root>
|
||||||
|
);
|
||||||
|
|
||||||
|
const Styled: Record<string, AnyStyledComponent> = {};
|
||||||
|
|
||||||
|
Styled.Root = styled(Root)`
|
||||||
|
--accordion-paddingY: 1rem;
|
||||||
|
--accordion-paddingX: 1rem;
|
||||||
|
|
||||||
|
@media ${breakpoints.notTablet} {
|
||||||
|
--accordion-paddingX: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
> *:not(:last-child) {
|
||||||
|
border-bottom: var(--border-width) solid var(--border-color);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Item = styled(Item)``;
|
||||||
|
|
||||||
|
Styled.Icon = styled.div`
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
width: 2.25rem;
|
||||||
|
height: 2.25rem;
|
||||||
|
|
||||||
|
--color-border: var(--color-layer-6);
|
||||||
|
color: var(--color-text-1);
|
||||||
|
background-color: var(--color-layer-5);
|
||||||
|
border: solid var(--border-width) var(--color-border);
|
||||||
|
border-radius: 50%;
|
||||||
|
font: var(--font-small-book);
|
||||||
|
|
||||||
|
svg {
|
||||||
|
height: 1.125em;
|
||||||
|
width: 1.125em;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Trigger = styled(Trigger)`
|
||||||
|
${layoutMixins.spacedRow}
|
||||||
|
width: 100%;
|
||||||
|
padding: var(--accordion-paddingY) var(--accordion-paddingX);
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
color: var(--color-text-1);
|
||||||
|
text-align: start;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
${Styled.Icon} {
|
||||||
|
color: var(--color-text-2);
|
||||||
|
filter: brightness(var(--hover-filter-base));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
color: var(--color-text-0);
|
||||||
|
transition: transform 0.3s var(--ease-out-expo);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-state='open'] svg {
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Content = styled(Content)`
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0 var(--accordion-paddingX) var(--accordion-paddingY);
|
||||||
|
|
||||||
|
color: var(--color-text-0);
|
||||||
|
|
||||||
|
&[data-state='open'] {
|
||||||
|
animation: ${keyframes`
|
||||||
|
from {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
height: var(--radix-accordion-content-height);
|
||||||
|
}
|
||||||
|
`} 0.3s var(--ease-out-expo);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-state='closed'] {
|
||||||
|
animation: ${keyframes`
|
||||||
|
from {
|
||||||
|
height: var(--radix-accordion-content-height);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
`} 0.1s var(--ease-in-expo);
|
||||||
|
}
|
||||||
|
`;
|
||||||
@ -40,9 +40,6 @@ const AlertContainer = styled.div<StyleProps>`
|
|||||||
case AlertType.Info: {
|
case AlertType.Info: {
|
||||||
return css`
|
return css`
|
||||||
--alert-accent-color: var(--color-text-1);
|
--alert-accent-color: var(--color-text-1);
|
||||||
|
|
||||||
--alert-default-background-opacity: 0.133; // Relative
|
|
||||||
// --alert-background: var(--color-layer-6); // Absolute
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
case AlertType.Success: {
|
case AlertType.Success: {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ const assetIcons = {
|
|||||||
'1INCH': '/currencies/1inch.png',
|
'1INCH': '/currencies/1inch.png',
|
||||||
AAVE: '/currencies/aave.png',
|
AAVE: '/currencies/aave.png',
|
||||||
ADA: '/currencies/ada.png',
|
ADA: '/currencies/ada.png',
|
||||||
|
AGIX: '/currencies/agix.png',
|
||||||
ALGO: '/currencies/algo.png',
|
ALGO: '/currencies/algo.png',
|
||||||
APE: '/currencies/ape.png',
|
APE: '/currencies/ape.png',
|
||||||
APT: '/currencies/apt.png',
|
APT: '/currencies/apt.png',
|
||||||
@ -16,35 +17,60 @@ const assetIcons = {
|
|||||||
AVAX: '/currencies/avax.png',
|
AVAX: '/currencies/avax.png',
|
||||||
BCH: '/currencies/bch.png',
|
BCH: '/currencies/bch.png',
|
||||||
BLUR: '/currencies/blur.png',
|
BLUR: '/currencies/blur.png',
|
||||||
|
BNB: '/currencies/bnb.png',
|
||||||
|
BONK: '/currencies/bonk.png',
|
||||||
BTC: '/currencies/btc.png',
|
BTC: '/currencies/btc.png',
|
||||||
CELO: '/currencies/celo.png',
|
CELO: '/currencies/celo.png',
|
||||||
|
CHZ: '/currencies/chz.png',
|
||||||
COMP: '/currencies/comp.png',
|
COMP: '/currencies/comp.png',
|
||||||
CRV: '/currencies/crv.png',
|
CRV: '/currencies/crv.png',
|
||||||
DAI: '/currencies/dai.png',
|
DAI: '/currencies/dai.png',
|
||||||
DOGE: '/currencies/doge.png',
|
DOGE: '/currencies/doge.png',
|
||||||
DOT: '/currencies/dot.png',
|
DOT: '/currencies/dot.png',
|
||||||
DYDX: '/currencies/dydx.png',
|
DYDX: '/currencies/dydx.png',
|
||||||
|
DYM: '/currencies/dym.png',
|
||||||
ENJ: '/currencies/enj.png',
|
ENJ: '/currencies/enj.png',
|
||||||
|
ENS: '/currencies/ens.png',
|
||||||
EOS: '/currencies/eos.png',
|
EOS: '/currencies/eos.png',
|
||||||
ETC: '/currencies/etc.png',
|
ETC: '/currencies/etc.png',
|
||||||
ETH: '/currencies/eth.png',
|
ETH: '/currencies/eth.png',
|
||||||
|
FET: '/currencies/fet.png',
|
||||||
FIL: '/currencies/fil.png',
|
FIL: '/currencies/fil.png',
|
||||||
|
FTM: '/currencies/ftm.png',
|
||||||
|
GALA: "/currencies/gala.png",
|
||||||
|
GMT: "/currencies/gmt.png",
|
||||||
|
GRT: "/currencies/grt.png",
|
||||||
|
HBAR: "/currencies/hbar.png",
|
||||||
ICP: '/currencies/icp.png',
|
ICP: '/currencies/icp.png',
|
||||||
|
IMX: '/currencies/imx.png',
|
||||||
|
INJ: '/currencies/inj.png',
|
||||||
|
JTO: '/currencies/jto.png',
|
||||||
|
JUP: '/currencies/jup.png',
|
||||||
|
KAVA: '/currencies/kava.png',
|
||||||
LDO: '/currencies/ldo.png',
|
LDO: '/currencies/ldo.png',
|
||||||
LINK: '/currencies/link.png',
|
LINK: '/currencies/link.png',
|
||||||
LTC: '/currencies/ltc.png',
|
LTC: '/currencies/ltc.png',
|
||||||
|
MANA: '/currencies/mana.png',
|
||||||
MATIC: '/currencies/matic.png',
|
MATIC: '/currencies/matic.png',
|
||||||
|
MASK: '/currencies/mask.png',
|
||||||
|
MINA: '/currencies/mina.png',
|
||||||
MKR: '/currencies/mkr.png',
|
MKR: '/currencies/mkr.png',
|
||||||
NEAR: '/currencies/near.png',
|
NEAR: '/currencies/near.png',
|
||||||
|
ORDI: "/currencies/ordi.png",
|
||||||
OP: '/currencies/op.png',
|
OP: '/currencies/op.png',
|
||||||
PEPE: '/currencies/pepe.png',
|
PEPE: '/currencies/pepe.png',
|
||||||
|
PYTH: '/currencies/pyth.png',
|
||||||
|
RNDR: '/currencies/rndr.png',
|
||||||
RUNE: '/currencies/rune.png',
|
RUNE: '/currencies/rune.png',
|
||||||
|
SAND: '/currencies/sand.png',
|
||||||
SEI: '/currencies/sei.png',
|
SEI: '/currencies/sei.png',
|
||||||
SHIB: '/currencies/shib.png',
|
SHIB: '/currencies/shib.png',
|
||||||
SNX: '/currencies/snx.png',
|
SNX: '/currencies/snx.png',
|
||||||
SOL: '/currencies/sol.png',
|
SOL: '/currencies/sol.png',
|
||||||
|
STX: '/currencies/stx.png',
|
||||||
SUI: '/currencies/sui.png',
|
SUI: '/currencies/sui.png',
|
||||||
SUSHI: '/currencies/sushi.png',
|
SUSHI: '/currencies/sushi.png',
|
||||||
|
TIA: '/currencies/tia.png',
|
||||||
TRX: '/currencies/trx.png',
|
TRX: '/currencies/trx.png',
|
||||||
UMA: '/currencies/uma.png',
|
UMA: '/currencies/uma.png',
|
||||||
UNI: '/currencies/uni.png',
|
UNI: '/currencies/uni.png',
|
||||||
@ -52,6 +78,7 @@ const assetIcons = {
|
|||||||
USDT: '/currencies/usdt.png',
|
USDT: '/currencies/usdt.png',
|
||||||
WBTC: '/currencies/wbtc.png',
|
WBTC: '/currencies/wbtc.png',
|
||||||
WETH: '/currencies/weth.png',
|
WETH: '/currencies/weth.png',
|
||||||
|
WOO: '/currencies/woo.png',
|
||||||
WLD: '/currencies/wld.png',
|
WLD: '/currencies/wld.png',
|
||||||
XLM: '/currencies/xlm.png',
|
XLM: '/currencies/xlm.png',
|
||||||
XMR: '/currencies/xmr.png',
|
XMR: '/currencies/xmr.png',
|
||||||
@ -59,6 +86,7 @@ const assetIcons = {
|
|||||||
XTZ: '/currencies/xtz.png',
|
XTZ: '/currencies/xtz.png',
|
||||||
YFI: '/currencies/yfi.png',
|
YFI: '/currencies/yfi.png',
|
||||||
ZEC: '/currencies/zec.png',
|
ZEC: '/currencies/zec.png',
|
||||||
|
ZETA: '/currencies/zeta.png',
|
||||||
ZRX: '/currencies/zrx.png',
|
ZRX: '/currencies/zrx.png',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
@ -71,8 +99,13 @@ export const AssetIcon = ({
|
|||||||
}: {
|
}: {
|
||||||
symbol?: Nullable<string>;
|
symbol?: Nullable<string>;
|
||||||
className?: string;
|
className?: string;
|
||||||
}) =>
|
}) => (
|
||||||
isAssetSymbol(symbol) ? <Styled.Img src={assetIcons[symbol]} className={className} /> : null;
|
<Styled.Img
|
||||||
|
src={isAssetSymbol(symbol) ? assetIcons[symbol] : '/currencies/unavailable.png'}
|
||||||
|
className={className}
|
||||||
|
alt={symbol}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
const Styled: Record<string, AnyStyledComponent> = {};
|
const Styled: Record<string, AnyStyledComponent> = {};
|
||||||
|
|
||||||
|
|||||||
@ -134,8 +134,8 @@ const ButtonStyle = css<StyleProps>`
|
|||||||
|
|
||||||
--button-textColor: var(--color-text-0);
|
--button-textColor: var(--color-text-0);
|
||||||
--button-backgroundColor: transparent;
|
--button-backgroundColor: transparent;
|
||||||
--button-active-filter: brightness(0.9);
|
--button-active-filter: brightness(var(--active-filter));
|
||||||
--button-hover-filter: brightness(1.1);
|
--button-hover-filter: brightness(var(--hover-filter-base));
|
||||||
--button-hover-textColor: var(--button-textColor);
|
--button-hover-textColor: var(--button-textColor);
|
||||||
|
|
||||||
--button-radius: 0.5em;
|
--button-radius: 0.5em;
|
||||||
|
|||||||
@ -61,7 +61,7 @@ export const Button = forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonPr
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledBaseButton
|
<StyledBaseButton
|
||||||
disabled={state[ButtonState.Disabled]}
|
disabled={state[ButtonState.Disabled] || state[ButtonState.Loading]}
|
||||||
{...{ ref, action, size, shape, state, ...otherProps }}
|
{...{ ref, action, size, shape, state, ...otherProps }}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
@ -89,9 +89,10 @@ const buttonActionVariants = {
|
|||||||
--button-border: solid var(--border-width) var(--color-border);
|
--button-border: solid var(--border-width) var(--color-border);
|
||||||
`,
|
`,
|
||||||
[ButtonAction.Primary]: css`
|
[ButtonAction.Primary]: css`
|
||||||
--button-textColor: var(--color-text-2);
|
--button-textColor: var(--color-text-button);
|
||||||
--button-backgroundColor: var(--color-accent);
|
--button-backgroundColor: var(--color-accent);
|
||||||
--button-border: solid var(--border-width) var(--color-border-white);
|
--button-border: solid var(--border-width) var(--color-border-white);
|
||||||
|
--button-hover-filter: brightness(var(--hover-filter-variant));
|
||||||
`,
|
`,
|
||||||
|
|
||||||
[ButtonAction.Secondary]: css`
|
[ButtonAction.Secondary]: css`
|
||||||
@ -101,15 +102,17 @@ const buttonActionVariants = {
|
|||||||
`,
|
`,
|
||||||
|
|
||||||
[ButtonAction.Create]: css`
|
[ButtonAction.Create]: css`
|
||||||
--button-textColor: var(--color-text-2);
|
--button-textColor: var(--color-text-button);
|
||||||
--button-backgroundColor: var(--color-positive);
|
--button-backgroundColor: var(--color-green);
|
||||||
--button-border: solid var(--border-width) var(--color-border-white);
|
--button-border: solid var(--border-width) var(--color-border-white);
|
||||||
|
--button-hover-filter: brightness(var(--hover-filter-variant));
|
||||||
`,
|
`,
|
||||||
|
|
||||||
[ButtonAction.Destroy]: css`
|
[ButtonAction.Destroy]: css`
|
||||||
--button-textColor: var(--color-text-2);
|
--button-textColor: var(--color-text-button);
|
||||||
--button-backgroundColor: var(--color-negative);
|
--button-backgroundColor: var(--color-red);
|
||||||
--button-border: solid var(--border-width) var(--color-border-white);
|
--button-border: solid var(--border-width) var(--color-border-white);
|
||||||
|
--button-hover-filter: brightness(var(--hover-filter-variant));
|
||||||
`,
|
`,
|
||||||
|
|
||||||
[ButtonAction.Navigation]: css`
|
[ButtonAction.Navigation]: css`
|
||||||
@ -119,9 +122,10 @@ const buttonActionVariants = {
|
|||||||
`,
|
`,
|
||||||
|
|
||||||
[ButtonAction.Reset]: css`
|
[ButtonAction.Reset]: css`
|
||||||
--button-textColor: var(--color-negative);
|
--button-textColor: var(--color-red);
|
||||||
--button-backgroundColor: var(--color-layer-3);
|
--button-backgroundColor: var(--color-layer-3);
|
||||||
--button-border: solid var(--border-width) var(--color-border-red);
|
--button-border: solid var(--border-width) var(--color-border-red);
|
||||||
|
--button-hover-filter: brightness(var(--hover-filter-variant));
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
13
src/components/Canvas.tsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { forwardRef } from 'react';
|
||||||
|
|
||||||
|
type CanvasProps = {
|
||||||
|
className?: string;
|
||||||
|
width: number | string;
|
||||||
|
height: number | string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Canvas = forwardRef<HTMLCanvasElement, CanvasProps>(
|
||||||
|
({ className, width, height }, canvasRef) => (
|
||||||
|
<canvas ref={canvasRef} className={className} width={width} height={height} />
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -5,7 +5,7 @@ import { Checkbox, CheckboxProps } from '@/components/Checkbox';
|
|||||||
|
|
||||||
import { StoryWrapper } from '.ladle/components';
|
import { StoryWrapper } from '.ladle/components';
|
||||||
|
|
||||||
export const Checkboxes: Story<CheckboxProps> = (args) => {
|
export const CheckboxStory: Story<CheckboxProps> = (args) => {
|
||||||
const [isChecked, setIsChecked] = useState(false);
|
const [isChecked, setIsChecked] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -13,10 +13,20 @@ export const Checkboxes: Story<CheckboxProps> = (args) => {
|
|||||||
<Checkbox
|
<Checkbox
|
||||||
{...args}
|
{...args}
|
||||||
checked={isChecked}
|
checked={isChecked}
|
||||||
onClick={(e: React.ChangeEvent) => setIsChecked((e.target as HTMLInputElement).checked)}
|
onCheckedChange={setIsChecked}
|
||||||
|
id="story-checkbox"
|
||||||
|
label="example label"
|
||||||
/>
|
/>
|
||||||
</StoryWrapper>
|
</StoryWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Checkboxes.args = {};
|
CheckboxStory.args = {};
|
||||||
|
|
||||||
|
CheckboxStory.argTypes = {
|
||||||
|
disabled: {
|
||||||
|
options: [true, false],
|
||||||
|
control: { type: 'select' },
|
||||||
|
defaultValue: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,10 +1,15 @@
|
|||||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
import styled, { css, type AnyStyledComponent } from 'styled-components';
|
||||||
|
import { Root, Indicator } from '@radix-ui/react-checkbox';
|
||||||
|
import { CheckIcon } from '@radix-ui/react-icons';
|
||||||
|
|
||||||
import { breakpoints } from '@/styles';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
type ElementProps = {
|
type ElementProps = {
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
onClick: (e: React.ChangeEvent) => void;
|
onCheckedChange: (checked: boolean) => void;
|
||||||
|
id?: string;
|
||||||
|
label?: React.ReactNode;
|
||||||
|
disabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StyleProps = {
|
type StyleProps = {
|
||||||
@ -13,85 +18,79 @@ type StyleProps = {
|
|||||||
|
|
||||||
export type CheckboxProps = ElementProps & StyleProps;
|
export type CheckboxProps = ElementProps & StyleProps;
|
||||||
|
|
||||||
export const Checkbox: React.FC<CheckboxProps> = ({ checked, className, onClick }) => {
|
export const Checkbox: React.FC<CheckboxProps> = ({
|
||||||
return (
|
checked,
|
||||||
<Styled.CheckboxWrapper className={className}>
|
className,
|
||||||
<Styled.Checkbox
|
onCheckedChange,
|
||||||
type="checkbox"
|
id,
|
||||||
checked={checked}
|
label,
|
||||||
onChange={onClick}
|
disabled,
|
||||||
/>
|
}) => (
|
||||||
<Styled.CustomCheckbox />
|
<Styled.Container>
|
||||||
</Styled.CheckboxWrapper>
|
<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>
|
||||||
|
)}
|
||||||
|
</Styled.Container>
|
||||||
|
);
|
||||||
|
|
||||||
const Styled: Record<string, AnyStyledComponent> = {};
|
const Styled: Record<string, AnyStyledComponent> = {};
|
||||||
|
|
||||||
Styled.CustomCheckbox = styled.span`
|
Styled.Container = styled.div`
|
||||||
width: 1.25em;
|
${layoutMixins.row}
|
||||||
height: 1.25em;
|
gap: 1ch;
|
||||||
|
font: var(--font-small-book);
|
||||||
|
`;
|
||||||
|
|
||||||
position: absolute;
|
Styled.Root = styled(Root)`
|
||||||
left: 0;
|
--checkbox-backgroundColor: var(--color-layer-0);
|
||||||
right: 0;
|
--checkbox-borderColor: var(--color-border);
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
min-width: 1.25rem;
|
||||||
|
height: 1.25rem;
|
||||||
|
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
border: var(--border-width) solid var(--checkbox-borderColor);
|
||||||
background-color: var(--checkbox-backgroundColor);
|
background-color: var(--checkbox-backgroundColor);
|
||||||
|
|
||||||
&::after {
|
&[data-state='checked'] {
|
||||||
position: absolute;
|
--checkbox-backgroundColor: var(--color-accent);
|
||||||
content: '';
|
|
||||||
top: 0.25em;
|
|
||||||
left: 0.4375em;
|
|
||||||
width: 0.3125em;
|
|
||||||
height: 0.5em;
|
|
||||||
border: solid var(--checkbox-checkColor);
|
|
||||||
border-width: 0 0.125em 0.125em 0;
|
|
||||||
border-radius: 0.0625em;
|
|
||||||
opacity: 0;
|
|
||||||
transform: rotate(0deg) scale(0);
|
|
||||||
transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media ${breakpoints.tablet} {
|
&[data-disabled] {
|
||||||
width: 1.5em;
|
cursor: not-allowed;
|
||||||
height: 1.5em;
|
--checkbox-backgroundColor: var(--color-layer-1);
|
||||||
|
|
||||||
&::after {
|
|
||||||
top: 0.25em;
|
|
||||||
left: 0.4375em;
|
|
||||||
width: 0.4375em;
|
|
||||||
height: 0.625em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.CheckboxWrapper = styled.div`
|
Styled.Indicator = styled(Indicator)`
|
||||||
--checkbox-backgroundColor: var(--color-layer-1);
|
|
||||||
--checkbox-checkColor: var(--color-text-1);
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
border-radius: 0.25em;
|
align-items: center;
|
||||||
overflow: hidden;
|
justify-content: center;
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
> input:checked ~ ${Styled.CustomCheckbox}::after {
|
color: var(--color-text-button);
|
||||||
opacity: 1;
|
|
||||||
transform: rotate(40deg) scale(1);
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Checkbox = styled.input`
|
Styled.Label = styled.label<{ disabled?: boolean }>`
|
||||||
width: 1.25em;
|
|
||||||
height: 1.25em;
|
|
||||||
z-index: 1;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
opacity: 0;
|
color: var(--color-text-2);
|
||||||
|
|
||||||
@media ${breakpoints.tablet} {
|
${({ disabled }) =>
|
||||||
width: 1.5em;
|
disabled &&
|
||||||
height: 1.5em;
|
css`
|
||||||
}
|
cursor: not-allowed;
|
||||||
|
color: var(--color-text-0);
|
||||||
|
`}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -1,16 +1,13 @@
|
|||||||
import type { Story } from '@ladle/react';
|
import type { Story } from '@ladle/react';
|
||||||
|
|
||||||
import { Collapsible } from '@/components/Collapsible';
|
import { Collapsible, type CollapsibleProps } from '@/components/Collapsible';
|
||||||
|
|
||||||
import { StoryWrapper } from '.ladle/components';
|
import { StoryWrapper } from '.ladle/components';
|
||||||
import { IconName } from './Icon';
|
import { IconName } from './Icon';
|
||||||
|
|
||||||
export const CollapsibleStory: Story<Parameters<typeof Collapsible>> = (args) => (
|
export const CollapsibleStory: Story<CollapsibleProps> = (args) => (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<Collapsible
|
<Collapsible {...args}>
|
||||||
label="Collapsible List of Items"
|
|
||||||
{...args}
|
|
||||||
>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Collapsible Item 1</li>
|
<li>Collapsible Item 1</li>
|
||||||
<li>Collapsible Item 2</li>
|
<li>Collapsible Item 2</li>
|
||||||
@ -23,6 +20,8 @@ export const CollapsibleStory: Story<Parameters<typeof Collapsible>> = (args) =>
|
|||||||
|
|
||||||
CollapsibleStory.args = {
|
CollapsibleStory.args = {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
withTrigger: true,
|
||||||
|
label: 'Collapsible List of Items',
|
||||||
};
|
};
|
||||||
|
|
||||||
CollapsibleStory.argTypes = {
|
CollapsibleStory.argTypes = {
|
||||||
|
|||||||
@ -14,6 +14,7 @@ type ElementProps = {
|
|||||||
label: React.ReactNode;
|
label: React.ReactNode;
|
||||||
triggerIcon?: IconName;
|
triggerIcon?: IconName;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
withTrigger?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StyleProps = {
|
type StyleProps = {
|
||||||
@ -23,6 +24,8 @@ type StyleProps = {
|
|||||||
fullWidth?: boolean;
|
fullWidth?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CollapsibleProps = ElementProps & StyleProps;
|
||||||
|
|
||||||
export const Collapsible = ({
|
export const Collapsible = ({
|
||||||
defaultOpen = false,
|
defaultOpen = false,
|
||||||
disabled,
|
disabled,
|
||||||
@ -35,26 +38,29 @@ export const Collapsible = ({
|
|||||||
triggerIconSide = 'left',
|
triggerIconSide = 'left',
|
||||||
fullWidth,
|
fullWidth,
|
||||||
className,
|
className,
|
||||||
}: ElementProps & StyleProps) => (
|
withTrigger = true,
|
||||||
|
}: CollapsibleProps) => (
|
||||||
<Styled.Root defaultOpen={defaultOpen} open={open} onOpenChange={onOpenChange}>
|
<Styled.Root defaultOpen={defaultOpen} open={open} onOpenChange={onOpenChange}>
|
||||||
<Styled.Trigger className={className} disabled={disabled}>
|
{withTrigger && (
|
||||||
{triggerIconSide === 'right' && (
|
<Styled.Trigger className={className} disabled={disabled}>
|
||||||
<>
|
{triggerIconSide === 'right' && (
|
||||||
{label}
|
<>
|
||||||
{fullWidth && <HorizontalSeparatorFiller />}
|
{label}
|
||||||
</>
|
{fullWidth && <HorizontalSeparatorFiller />}
|
||||||
)}
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<Styled.TriggerIcon>
|
<Styled.TriggerIcon>
|
||||||
<Icon iconName={triggerIcon} />
|
<Icon iconName={triggerIcon} />
|
||||||
</Styled.TriggerIcon>
|
</Styled.TriggerIcon>
|
||||||
{triggerIconSide === 'left' && (
|
{triggerIconSide === 'left' && (
|
||||||
<>
|
<>
|
||||||
{fullWidth && <HorizontalSeparatorFiller />}
|
{fullWidth && <HorizontalSeparatorFiller />}
|
||||||
{label}
|
{label}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Styled.Trigger>
|
</Styled.Trigger>
|
||||||
|
)}
|
||||||
<Styled.Content $transitionDuration={transitionDuration}>{children}</Styled.Content>
|
<Styled.Content $transitionDuration={transitionDuration}>{children}</Styled.Content>
|
||||||
</Styled.Root>
|
</Styled.Root>
|
||||||
);
|
);
|
||||||
@ -80,7 +86,7 @@ Styled.TriggerIcon = styled.span`
|
|||||||
width: var(--trigger-icon-width);
|
width: var(--trigger-icon-width);
|
||||||
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
transition: transform 0.3s var(--ease-out-expo);
|
transition: rotate 0.3s var(--ease-out-expo);
|
||||||
color: var(--trigger-icon-color);
|
color: var(--trigger-icon-color);
|
||||||
|
|
||||||
${Styled.Trigger}[data-state='open'] & {
|
${Styled.Trigger}[data-state='open'] & {
|
||||||
|
|||||||
@ -31,10 +31,12 @@ type ElementProps<TabItemsValue> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type StyleProps = {
|
type StyleProps = {
|
||||||
fullWidthTabs?: boolean;
|
|
||||||
className?: string;
|
className?: string;
|
||||||
|
fullWidthTabs?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CollapsibleTabsProps<TabItemsValue> = ElementProps<TabItemsValue> & StyleProps;
|
||||||
|
|
||||||
export const CollapsibleTabs = <TabItemsValue extends string>({
|
export const CollapsibleTabs = <TabItemsValue extends string>({
|
||||||
defaultValue,
|
defaultValue,
|
||||||
items,
|
items,
|
||||||
@ -43,8 +45,9 @@ export const CollapsibleTabs = <TabItemsValue extends string>({
|
|||||||
onOpenChange,
|
onOpenChange,
|
||||||
|
|
||||||
fullWidthTabs,
|
fullWidthTabs,
|
||||||
|
|
||||||
className,
|
className,
|
||||||
}: ElementProps<TabItemsValue> & StyleProps) => {
|
}: CollapsibleTabsProps<TabItemsValue>) => {
|
||||||
const [value, setValue] = useState(defaultValue);
|
const [value, setValue] = useState(defaultValue);
|
||||||
|
|
||||||
const currentItem = items.find((item) => item.value === value);
|
const currentItem = items.find((item) => item.value === value);
|
||||||
@ -86,8 +89,8 @@ export const CollapsibleTabs = <TabItemsValue extends string>({
|
|||||||
</Styled.Header>
|
</Styled.Header>
|
||||||
|
|
||||||
<Styled.CollapsibleContent>
|
<Styled.CollapsibleContent>
|
||||||
{items.map(({ value, content }) => (
|
{items.map(({ asChild, value, content }) => (
|
||||||
<Styled.TabsContent key={value} value={value}>
|
<Styled.TabsContent key={value} asChild={asChild} value={value}>
|
||||||
{content}
|
{content}
|
||||||
</Styled.TabsContent>
|
</Styled.TabsContent>
|
||||||
))}
|
))}
|
||||||
@ -219,12 +222,12 @@ Styled.Header = styled.header`
|
|||||||
|
|
||||||
Styled.CollapsibleContent = styled(CollapsibleContent)`
|
Styled.CollapsibleContent = styled(CollapsibleContent)`
|
||||||
${layoutMixins.stack}
|
${layoutMixins.stack}
|
||||||
${layoutMixins.perspectiveArea}
|
|
||||||
|
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.IconButton = styled(IconButton)`
|
Styled.IconButton = styled(IconButton)`
|
||||||
|
--button-icon-size: 1em;
|
||||||
${Styled.CollapsibleRoot}[data-state='closed'] & {
|
${Styled.CollapsibleRoot}[data-state='closed'] & {
|
||||||
rotate: -0.5turn;
|
rotate: -0.5turn;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,12 @@ type PickComboxMenuProps<
|
|||||||
MenuGroupValue extends string | number
|
MenuGroupValue extends string | number
|
||||||
> = Pick<
|
> = Pick<
|
||||||
ComboboxMenuProps<MenuItemValue, MenuGroupValue>,
|
ComboboxMenuProps<MenuItemValue, MenuGroupValue>,
|
||||||
'inputPlaceholder' | 'onItemSelected' | 'slotEmpty' | 'withSearch' | 'withStickyLayout'
|
| 'inputPlaceholder'
|
||||||
|
| 'onItemSelected'
|
||||||
|
| 'slotEmpty'
|
||||||
|
| 'withItemBorders'
|
||||||
|
| 'withSearch'
|
||||||
|
| 'withStickyLayout'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type PickDialogProps = Pick<
|
type PickDialogProps = Pick<
|
||||||
@ -34,6 +39,7 @@ type PickDialogProps = Pick<
|
|||||||
| 'slotHeaderInner'
|
| 'slotHeaderInner'
|
||||||
| 'slotTrigger'
|
| 'slotTrigger'
|
||||||
| 'slotFooter'
|
| 'slotFooter'
|
||||||
|
| 'preventClose'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export const ComboboxDialogMenu = <
|
export const ComboboxDialogMenu = <
|
||||||
@ -52,11 +58,13 @@ export const ComboboxDialogMenu = <
|
|||||||
onItemSelected,
|
onItemSelected,
|
||||||
inputPlaceholder,
|
inputPlaceholder,
|
||||||
slotEmpty,
|
slotEmpty,
|
||||||
|
withItemBorders,
|
||||||
withSearch,
|
withSearch,
|
||||||
withStickyLayout = true,
|
withStickyLayout = true,
|
||||||
children,
|
children,
|
||||||
|
|
||||||
placement = DialogPlacement.Default,
|
placement = DialogPlacement.Default,
|
||||||
|
preventClose,
|
||||||
className,
|
className,
|
||||||
}: ElementProps<MenuItemValue, MenuGroupValue> &
|
}: ElementProps<MenuItemValue, MenuGroupValue> &
|
||||||
PickComboxMenuProps<MenuItemValue, MenuGroupValue> &
|
PickComboxMenuProps<MenuItemValue, MenuGroupValue> &
|
||||||
@ -72,6 +80,7 @@ export const ComboboxDialogMenu = <
|
|||||||
slotTrigger={slotTrigger}
|
slotTrigger={slotTrigger}
|
||||||
slotFooter={slotFooter}
|
slotFooter={slotFooter}
|
||||||
placement={placement}
|
placement={placement}
|
||||||
|
preventClose={preventClose}
|
||||||
className={className}
|
className={className}
|
||||||
>
|
>
|
||||||
<Styled.ComboboxMenu
|
<Styled.ComboboxMenu
|
||||||
@ -80,6 +89,7 @@ export const ComboboxDialogMenu = <
|
|||||||
title={title}
|
title={title}
|
||||||
inputPlaceholder={inputPlaceholder}
|
inputPlaceholder={inputPlaceholder}
|
||||||
slotEmpty={slotEmpty}
|
slotEmpty={slotEmpty}
|
||||||
|
withItemBorders={withItemBorders}
|
||||||
withSearch={withSearch}
|
withSearch={withSearch}
|
||||||
withStickyLayout={withStickyLayout}
|
withStickyLayout={withStickyLayout}
|
||||||
/>
|
/>
|
||||||
@ -92,6 +102,8 @@ const Styled: Record<string, AnyStyledComponent> = {};
|
|||||||
Styled.Dialog = styled(Dialog)`
|
Styled.Dialog = styled(Dialog)`
|
||||||
/* Params */
|
/* Params */
|
||||||
--comboboxDialogMenu-backgroundColor: var(--color-layer-2);
|
--comboboxDialogMenu-backgroundColor: var(--color-layer-2);
|
||||||
|
--comboboxDialogMenu-item-gap: 0.5rem;
|
||||||
|
--comboboxDialogMenu-item-padding: 0.5rem 1rem;
|
||||||
|
|
||||||
/* Overrides */
|
/* Overrides */
|
||||||
& {
|
& {
|
||||||
@ -110,10 +122,12 @@ Styled.Dialog = styled(Dialog)`
|
|||||||
|
|
||||||
/* Net 0 sticky top inset (let stickyArea1 header stick to top) */
|
/* Net 0 sticky top inset (let stickyArea1 header stick to top) */
|
||||||
--stickyArea0-topGap: calc(-1 * var(--stickyArea0-topHeight));
|
--stickyArea0-topGap: calc(-1 * var(--stickyArea0-topHeight));
|
||||||
|
overflow-x: clip;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.ComboboxMenu = styled(ComboboxMenu)`
|
Styled.ComboboxMenu = styled(ComboboxMenu)`
|
||||||
--comboboxMenu-backgroundColor: var(--comboboxDialogMenu-backgroundColor);
|
--comboboxMenu-backgroundColor: var(--comboboxDialogMenu-backgroundColor);
|
||||||
--comboboxMenu-item-gap: var(--comboxDialogMenu-item-gap, 0.5rem);
|
--comboboxMenu-item-gap: var(--comboboxDialogMenu-item-gap);
|
||||||
|
--comboboxMenu-item-padding: var(--comboboxDialogMenu-item-padding);
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { Fragment, type ReactNode, useState } from 'react';
|
|||||||
import styled, { type AnyStyledComponent, css } from 'styled-components';
|
import styled, { type AnyStyledComponent, css } from 'styled-components';
|
||||||
import { Command } from 'cmdk';
|
import { Command } from 'cmdk';
|
||||||
|
|
||||||
import { type MenuConfig } from '@/constants/menus';
|
import { MenuItem, type MenuConfig } from '@/constants/menus';
|
||||||
import { popoverMixins } from '@/styles/popoverMixins';
|
import { popoverMixins } from '@/styles/popoverMixins';
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
@ -20,6 +20,7 @@ type ElementProps<MenuItemValue extends string | number, MenuGroupValue extends
|
|||||||
|
|
||||||
type StyleProps = {
|
type StyleProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
withItemBorders?: boolean;
|
||||||
withStickyLayout?: boolean;
|
withStickyLayout?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -38,38 +39,36 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
|
|||||||
withSearch = true,
|
withSearch = true,
|
||||||
|
|
||||||
className,
|
className,
|
||||||
|
withItemBorders,
|
||||||
withStickyLayout,
|
withStickyLayout,
|
||||||
}: ComboboxMenuProps<MenuItemValue, MenuGroupValue>) => {
|
}: ComboboxMenuProps<MenuItemValue, MenuGroupValue>) => {
|
||||||
const [highlightedCommand, setHighlightedCommand] = useState<MenuItemValue>();
|
const [highlightedCommand, setHighlightedCommand] = useState<MenuItemValue>();
|
||||||
const [searchValue, setSearchValue] = useState('');
|
const [searchValue, setSearchValue] = useState('');
|
||||||
// const inputRef = useRef<HTMLInputElement | null>(null);
|
|
||||||
|
|
||||||
// console.log({ commandValue: highlightedCommand });
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// inputRef?.current?.focus();
|
|
||||||
// }, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Styled.Command
|
<Styled.Command
|
||||||
label={title}
|
label={title}
|
||||||
// value={highlightedCommand}
|
// value={highlightedCommand}
|
||||||
// onValueChange={setHighlightedCommand}
|
// onValueChange={setHighlightedCommand}
|
||||||
filter={(value: string, search: string) => {
|
filter={(value: string, search: string) =>
|
||||||
if (value.replace(/ /g, '').includes(search.replace(/ /g, ''))) return 1;
|
value.replace(/ /g, '').toLowerCase().includes(search.replace(/ /g, '').toLowerCase())
|
||||||
return 0;
|
? 1
|
||||||
}}
|
: 0
|
||||||
|
}
|
||||||
className={className}
|
className={className}
|
||||||
$withStickyLayout={withStickyLayout}
|
$withStickyLayout={withStickyLayout}
|
||||||
>
|
>
|
||||||
{withSearch && (
|
{withSearch && (
|
||||||
<Styled.Header $withStickyLayout={withStickyLayout}>
|
<Styled.Header $withStickyLayout={withStickyLayout}>
|
||||||
<Styled.Input
|
<Styled.Input
|
||||||
// ref={inputRef}
|
/**
|
||||||
|
* Mobile Issue: Search Input will always trigger mobile keyboard drawer. There is no fix.
|
||||||
|
* https://github.com/pacocoursey/cmdk/issues/127
|
||||||
|
*/
|
||||||
|
autoFocus
|
||||||
type="search"
|
type="search"
|
||||||
value={searchValue}
|
value={searchValue}
|
||||||
onValueChange={setSearchValue}
|
onValueChange={setSearchValue}
|
||||||
autoFocus
|
|
||||||
placeholder={inputPlaceholder}
|
placeholder={inputPlaceholder}
|
||||||
/>
|
/>
|
||||||
</Styled.Header>
|
</Styled.Header>
|
||||||
@ -80,6 +79,7 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
|
|||||||
<Styled.Group
|
<Styled.Group
|
||||||
key={group.group}
|
key={group.group}
|
||||||
heading={group.groupLabel}
|
heading={group.groupLabel}
|
||||||
|
$withItemBorders={withItemBorders}
|
||||||
$withStickyLayout={withStickyLayout}
|
$withStickyLayout={withStickyLayout}
|
||||||
>
|
>
|
||||||
{group.items.map((item) => (
|
{group.items.map((item) => (
|
||||||
@ -99,22 +99,31 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
disabled={item.disabled}
|
disabled={item.disabled}
|
||||||
|
$withItemBorders={withItemBorders}
|
||||||
>
|
>
|
||||||
{item.slotBefore}
|
{
|
||||||
<Styled.ItemLabel>
|
<>
|
||||||
<span>
|
{item.slotBefore}
|
||||||
{`${item.label}${item.subitems?.length ? '…' : ''}`}
|
{item.slotCustomContent ?? (
|
||||||
{item.tag && (
|
<Styled.ItemLabel>
|
||||||
<>
|
<span>
|
||||||
{' '}
|
{typeof item.label === 'string'
|
||||||
<Tag>{item.tag}</Tag>
|
? `${item.label}${item.subitems?.length ? '…' : ''}`
|
||||||
</>
|
: item.label}
|
||||||
|
{item.tag && (
|
||||||
|
<>
|
||||||
|
{' '}
|
||||||
|
<Tag>{item.tag}</Tag>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
{item.description && <span>{item.description}</span>}
|
||||||
|
</Styled.ItemLabel>
|
||||||
)}
|
)}
|
||||||
</span>
|
{item.slotAfter}
|
||||||
{item.description && <span>{item.description}</span>}
|
{item.subitems && '→'}
|
||||||
</Styled.ItemLabel>
|
</>
|
||||||
{item.slotAfter}
|
}
|
||||||
{item.subitems && '→'}
|
|
||||||
</Styled.Item>
|
</Styled.Item>
|
||||||
|
|
||||||
{searchValue &&
|
{searchValue &&
|
||||||
@ -137,6 +146,7 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
|
|||||||
onItemSelected?.();
|
onItemSelected?.();
|
||||||
}}
|
}}
|
||||||
disabled={subitem.disabled}
|
disabled={subitem.disabled}
|
||||||
|
$withItemBorders={withItemBorders}
|
||||||
>
|
>
|
||||||
{subitem.slotBefore}
|
{subitem.slotBefore}
|
||||||
<Styled.ItemLabel>
|
<Styled.ItemLabel>
|
||||||
@ -169,14 +179,17 @@ const Styled: Record<string, AnyStyledComponent> = {};
|
|||||||
|
|
||||||
Styled.Command = styled(Command)<{ $withStickyLayout?: boolean }>`
|
Styled.Command = styled(Command)<{ $withStickyLayout?: boolean }>`
|
||||||
--comboboxMenu-backgroundColor: var(--color-layer-2);
|
--comboboxMenu-backgroundColor: var(--color-layer-2);
|
||||||
|
|
||||||
--comboboxMenu-input-backgroundColor: var(--color-layer-3);
|
--comboboxMenu-input-backgroundColor: var(--color-layer-3);
|
||||||
--comboboxMenu-input-height: 2.5rem;
|
--comboboxMenu-input-height: 2.5rem;
|
||||||
|
|
||||||
--comboboxMenu-item-checked-backgroundColor: ;
|
--comboboxMenu-item-checked-backgroundColor: ;
|
||||||
--comboboxMenu-item-checked-textColor: ;
|
--comboboxMenu-item-checked-textColor: ;
|
||||||
--comboboxMenu-item-highlighted-backgroundColor: var(--color-layer-3);
|
--comboboxMenu-item-highlighted-backgroundColor: var(--color-layer-3);
|
||||||
--comboboxMenu-item-highlighted-textColor: var(--color-text-1);
|
--comboboxMenu-item-highlighted-textColor: var(--color-text-1);
|
||||||
--comboboxMenu-item-backgroundColor: ;
|
--comboboxMenu-item-backgroundColor: ;
|
||||||
--comboboxMenu-item-gap: 0.5rem;
|
--comboboxMenu-item-gap: 0.5rem;
|
||||||
|
--comboboxMenu-item-padding: 0.5em 1em;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
align-content: start;
|
align-content: start;
|
||||||
@ -225,7 +238,7 @@ Styled.Input = styled(Command.Input)`
|
|||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Group = styled(Command.Group)<{ $withStickyLayout?: boolean }>`
|
Styled.Group = styled(Command.Group)<{ $withItemBorders?: boolean; $withStickyLayout?: boolean }>`
|
||||||
color: var(--color-text-0);
|
color: var(--color-text-0);
|
||||||
|
|
||||||
> [cmdk-group-heading] {
|
> [cmdk-group-heading] {
|
||||||
@ -242,12 +255,21 @@ Styled.Group = styled(Command.Group)<{ $withStickyLayout?: boolean }>`
|
|||||||
|
|
||||||
> [cmdk-group-heading] {
|
> [cmdk-group-heading] {
|
||||||
${layoutMixins.stickyHeader}
|
${layoutMixins.stickyHeader}
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
> [cmdk-group-items] {
|
> [cmdk-group-items] {
|
||||||
${layoutMixins.stickyArea3}
|
${layoutMixins.stickyArea3}
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
|
|
||||||
|
${({ $withItemBorders }) =>
|
||||||
|
$withItemBorders &&
|
||||||
|
css`
|
||||||
|
> [cmdk-group-items] {
|
||||||
|
padding: var(--border-width) 0;
|
||||||
|
}
|
||||||
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.List = styled(Command.List)<{ $withStickyLayout?: boolean }>`
|
Styled.List = styled(Command.List)<{ $withStickyLayout?: boolean }>`
|
||||||
@ -274,13 +296,14 @@ Styled.List = styled(Command.List)<{ $withStickyLayout?: boolean }>`
|
|||||||
`}
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Item = styled(Command.Item)`
|
Styled.Item = styled(Command.Item)<{ $withItemBorders?: boolean }>`
|
||||||
${layoutMixins.scrollSnapItem}
|
${layoutMixins.scrollSnapItem}
|
||||||
${popoverMixins.item}
|
${popoverMixins.item}
|
||||||
--item-checked-backgroundColor: var(--comboboxMenu-item-checked-backgroundColor);
|
--item-checked-backgroundColor: var(--comboboxMenu-item-checked-backgroundColor);
|
||||||
--item-checked-textColor: var(--comboboxMenu-item-checked-textColor);
|
--item-checked-textColor: var(--comboboxMenu-item-checked-textColor);
|
||||||
--item-highlighted-textColor: var(--comboboxMenu-item-highlighted-textColor);
|
--item-highlighted-textColor: var(--comboboxMenu-item-highlighted-textColor);
|
||||||
--item-gap: var(--comboboxMenu-item-gap);
|
--item-gap: var(--comboboxMenu-item-gap);
|
||||||
|
--item-padding: var(--comboboxMenu-item-padding);
|
||||||
|
|
||||||
background-color: var(--comboboxMenu-backgroundColor, inherit);
|
background-color: var(--comboboxMenu-backgroundColor, inherit);
|
||||||
|
|
||||||
@ -291,6 +314,12 @@ Styled.Item = styled(Command.Item)`
|
|||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
${({ $withItemBorders }) =>
|
||||||
|
$withItemBorders &&
|
||||||
|
css`
|
||||||
|
${layoutMixins.withOuterBorder}
|
||||||
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.ItemLabel = styled.div`
|
Styled.ItemLabel = styled.div`
|
||||||
@ -309,6 +338,8 @@ Styled.ItemLabel = styled.div`
|
|||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
min-width: 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Empty = styled(Command.Empty)`
|
Styled.Empty = styled(Command.Empty)`
|
||||||
|
|||||||
@ -11,6 +11,5 @@ export const DetachedScrollableSection = styled.section`
|
|||||||
|
|
||||||
export const AttachedExpandingSection = styled.section`
|
export const AttachedExpandingSection = styled.section`
|
||||||
${layoutMixins.contentSectionAttached}
|
${layoutMixins.contentSectionAttached}
|
||||||
${layoutMixins.expandingColumnWithHeader}
|
|
||||||
gap: var(--border-width);
|
gap: var(--border-width);
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { layoutMixins } from '@/styles/layoutMixins';
|
|||||||
type ElementProps = {
|
type ElementProps = {
|
||||||
title: string;
|
title: string;
|
||||||
subtitle?: React.ReactNode;
|
subtitle?: React.ReactNode;
|
||||||
|
slotLeft?: React.ReactNode;
|
||||||
slotRight?: React.ReactNode;
|
slotRight?: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -16,14 +17,16 @@ type StyleProps = {
|
|||||||
export const ContentSectionHeader = ({
|
export const ContentSectionHeader = ({
|
||||||
title,
|
title,
|
||||||
subtitle,
|
subtitle,
|
||||||
|
slotLeft,
|
||||||
slotRight,
|
slotRight,
|
||||||
className,
|
className,
|
||||||
}: ElementProps & StyleProps) => (
|
}: ElementProps & StyleProps) => (
|
||||||
<Styled.ContentSectionHeader className={className}>
|
<Styled.ContentSectionHeader className={className}>
|
||||||
<div>
|
{slotLeft}
|
||||||
|
<Styled.Header>
|
||||||
{title && <h3>{title}</h3>}
|
{title && <h3>{title}</h3>}
|
||||||
{subtitle && <p>{subtitle}</p>}
|
{subtitle && <p>{subtitle}</p>}
|
||||||
</div>
|
</Styled.Header>
|
||||||
{slotRight}
|
{slotRight}
|
||||||
</Styled.ContentSectionHeader>
|
</Styled.ContentSectionHeader>
|
||||||
);
|
);
|
||||||
@ -40,9 +43,15 @@ Styled.ContentSectionHeader = styled.header<StyleProps>`
|
|||||||
|
|
||||||
padding: 1rem var(--header-horizontal-padding);
|
padding: 1rem var(--header-horizontal-padding);
|
||||||
|
|
||||||
> div {
|
@media ${breakpoints.tablet} {
|
||||||
${layoutMixins.column}
|
flex-wrap: wrap;
|
||||||
|
--header-horizontal-padding: 1.25rem;
|
||||||
}
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Header = styled.div`
|
||||||
|
${layoutMixins.column}
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
color: var(--color-text-2);
|
color: var(--color-text-2);
|
||||||
@ -54,9 +63,4 @@ Styled.ContentSectionHeader = styled.header<StyleProps>`
|
|||||||
font: var(--font-small-book);
|
font: var(--font-small-book);
|
||||||
margin-top: 0.25rem;
|
margin-top: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media ${breakpoints.tablet} {
|
|
||||||
flex-wrap: wrap;
|
|
||||||
--header-horizontal-padding: 1.25rem;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -15,10 +15,10 @@ CopyButtonStory.args = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
CopyButtonStory.argTypes = {
|
CopyButtonStory.argTypes = {
|
||||||
shownAsText: {
|
buttonType: {
|
||||||
options: [true, false],
|
options: ["text", "icon", "default"],
|
||||||
control: { type: 'select' },
|
control: { type: 'select' },
|
||||||
defaultValue: false,
|
defaultValue: "default",
|
||||||
},
|
},
|
||||||
children: {
|
children: {
|
||||||
options: ['some text to copy'],
|
options: ['some text to copy'],
|
||||||
|
|||||||
@ -9,14 +9,21 @@ import { layoutMixins } from '@/styles/layoutMixins';
|
|||||||
|
|
||||||
import { Button, ButtonProps } from './Button';
|
import { Button, ButtonProps } from './Button';
|
||||||
import { Icon, IconName } from './Icon';
|
import { Icon, IconName } from './Icon';
|
||||||
|
import { IconButton } from './IconButton';
|
||||||
|
import { WithTooltip } from './WithTooltip';
|
||||||
|
|
||||||
export type CopyButtonProps = {
|
export type CopyButtonProps = {
|
||||||
value?: string;
|
value?: string;
|
||||||
shownAsText?: boolean;
|
buttonType?: 'text' | 'icon' | 'default';
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
} & ButtonProps;
|
} & ButtonProps;
|
||||||
|
|
||||||
export const CopyButton = ({ value, shownAsText, children, ...buttonProps }: CopyButtonProps) => {
|
export const CopyButton = ({
|
||||||
|
value,
|
||||||
|
buttonType = 'default',
|
||||||
|
children,
|
||||||
|
...buttonProps
|
||||||
|
}: CopyButtonProps) => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
@ -28,11 +35,23 @@ export const CopyButton = ({ value, shownAsText, children, ...buttonProps }: Cop
|
|||||||
setTimeout(() => setCopied(false), 500);
|
setTimeout(() => setCopied(false), 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
return shownAsText ? (
|
return buttonType === 'text' ? (
|
||||||
<Styled.InlineRow onClick={onCopy} copied={copied}>
|
<Styled.InlineRow onClick={onCopy} copied={copied}>
|
||||||
{children}
|
{children}
|
||||||
<Icon iconName={IconName.Copy} />
|
<Styled.Icon copied={copied} iconName={copied ? IconName.Check : IconName.Copy} />
|
||||||
</Styled.InlineRow>
|
</Styled.InlineRow>
|
||||||
|
) : buttonType === 'icon' ? (
|
||||||
|
<WithTooltip
|
||||||
|
tooltipString={stringGetter({ key: copied ? STRING_KEYS.COPIED : STRING_KEYS.COPY })}
|
||||||
|
>
|
||||||
|
<Styled.IconButton
|
||||||
|
{...buttonProps}
|
||||||
|
copied={copied}
|
||||||
|
action={ButtonAction.Base}
|
||||||
|
iconName={copied ? IconName.Check : IconName.Copy}
|
||||||
|
onClick={onCopy}
|
||||||
|
/>
|
||||||
|
</WithTooltip>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
{...buttonProps}
|
{...buttonProps}
|
||||||
@ -58,8 +77,26 @@ Styled.InlineRow = styled.div<{ copied: boolean }>`
|
|||||||
`
|
`
|
||||||
: css`
|
: css`
|
||||||
&:hover {
|
&:hover {
|
||||||
filter: brightness(1.1);
|
filter: brightness(var(--hover-filter-base));
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
Styled.Icon = styled(Icon)<{ copied: boolean }>`
|
||||||
|
${({ copied }) =>
|
||||||
|
copied &&
|
||||||
|
css`
|
||||||
|
color: var(--color-success);
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.IconButton = styled(IconButton)<{ copied: boolean }>`
|
||||||
|
${({ copied }) =>
|
||||||
|
copied &&
|
||||||
|
css`
|
||||||
|
svg {
|
||||||
|
color: var(--color-success);
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|||||||
@ -7,35 +7,50 @@ import { StoryWrapper } from '.ladle/components';
|
|||||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
export const DetailsStory: Story<Parameters<typeof Details>> = () => (
|
export const DetailsStory: Story<Parameters<typeof Details>[0]> = (args) => (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<Styled.Resizable>
|
<Styled.Resizable>
|
||||||
<Details
|
<Details {...args} />
|
||||||
items={[
|
|
||||||
{
|
|
||||||
key: 'item-1',
|
|
||||||
label: 'Item 1',
|
|
||||||
tooltip: 'leverage',
|
|
||||||
value: 'Value 1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'item-2',
|
|
||||||
label: 'Really really really long item name 2',
|
|
||||||
tooltip: 'liquidation-price',
|
|
||||||
value: 'Value 2',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'item-3',
|
|
||||||
label: 'Item 3',
|
|
||||||
tooltip: 'realized-pnl',
|
|
||||||
value: 'Value 3',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</Styled.Resizable>
|
</Styled.Resizable>
|
||||||
</StoryWrapper>
|
</StoryWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DetailsStory.args = {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
key: 'item-1',
|
||||||
|
label: 'Item 1',
|
||||||
|
tooltip: 'leverage',
|
||||||
|
value: 'Value 1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'item-2',
|
||||||
|
label: 'Really really really long item name 2',
|
||||||
|
tooltip: 'liquidation-price',
|
||||||
|
value: 'Value 2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'item-3',
|
||||||
|
label: 'Item 3',
|
||||||
|
tooltip: 'realized-pnl',
|
||||||
|
value: 'Value 3',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
showSubitems: false,
|
||||||
|
isLoading: false,
|
||||||
|
withOverflow: false,
|
||||||
|
withSeparators: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
DetailsStory.argTypes = {
|
||||||
|
justifyItems: { options: ['start', 'end'], control: { type: 'select' }, defaultValue: 'start' },
|
||||||
|
layout: {
|
||||||
|
options: ['column', 'row', 'rowColumns', 'grid', 'stackColumn'],
|
||||||
|
control: { type: 'select' },
|
||||||
|
defaultValue: 'column',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const Styled: Record<string, AnyStyledComponent> = {};
|
const Styled: Record<string, AnyStyledComponent> = {};
|
||||||
|
|
||||||
Styled.Resizable = styled.section`
|
Styled.Resizable = styled.section`
|
||||||
|
|||||||
@ -133,6 +133,7 @@ const detailsLayoutVariants = {
|
|||||||
row: css`
|
row: css`
|
||||||
${layoutMixins.row}
|
${layoutMixins.row}
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
|
white-space: nowrap;
|
||||||
`,
|
`,
|
||||||
|
|
||||||
rowColumns: css`
|
rowColumns: css`
|
||||||
@ -159,12 +160,16 @@ const itemLayoutVariants: Record<string, FlattenInterpolation<ThemeProps<any>>>
|
|||||||
|
|
||||||
${layoutMixins.spacedRow}
|
${layoutMixins.spacedRow}
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
align-items: start;
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
|
||||||
min-height: var(--details-item-height);
|
min-height: var(--details-item-height);
|
||||||
|
|
||||||
> :last-child {
|
> :first-child > abbr {
|
||||||
align-self: stretch;
|
min-width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
> :last-child {
|
||||||
${layoutMixins.row}
|
${layoutMixins.row}
|
||||||
${layoutMixins.stickyRight}
|
${layoutMixins.stickyRight}
|
||||||
|
|
||||||
@ -217,8 +222,6 @@ Styled.Details = styled.dl<{
|
|||||||
--details-grid-numColumns: 2;
|
--details-grid-numColumns: 2;
|
||||||
|
|
||||||
${({ layout }) => layout && detailsLayoutVariants[layout]}
|
${({ layout }) => layout && detailsLayoutVariants[layout]}
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Item = styled.div<{
|
Styled.Item = styled.div<{
|
||||||
@ -231,7 +234,7 @@ Styled.Item = styled.div<{
|
|||||||
${({ justifyItems }) =>
|
${({ justifyItems }) =>
|
||||||
justifyItems === 'end' &&
|
justifyItems === 'end' &&
|
||||||
css`
|
css`
|
||||||
&:nth-child(even) {
|
> :nth-child(even) {
|
||||||
justify-items: end;
|
justify-items: end;
|
||||||
text-align: end;
|
text-align: end;
|
||||||
}
|
}
|
||||||
@ -243,6 +246,7 @@ Styled.Item = styled.div<{
|
|||||||
{
|
{
|
||||||
column: css`
|
column: css`
|
||||||
&:not(:hover) > :first-child {
|
&:not(:hover) > :first-child {
|
||||||
|
white-space: nowrap;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export const DetailsDialog = ({ slotIcon, title, items, slotFooter, setIsOpen }:
|
|||||||
placement={isTablet ? DialogPlacement.Default : DialogPlacement.Sidebar}
|
placement={isTablet ? DialogPlacement.Default : DialogPlacement.Sidebar}
|
||||||
>
|
>
|
||||||
<Styled.Content>
|
<Styled.Content>
|
||||||
<Styled.Details withSeparators items={items} />
|
<Styled.Details withSeparators justifyItems="end" items={items} />
|
||||||
|
|
||||||
<Styled.Footer>{slotFooter}</Styled.Footer>
|
<Styled.Footer>{slotFooter}</Styled.Footer>
|
||||||
</Styled.Content>
|
</Styled.Content>
|
||||||
|
|||||||
@ -38,6 +38,7 @@ type ElementProps = {
|
|||||||
slotTrigger?: React.ReactNode;
|
slotTrigger?: React.ReactNode;
|
||||||
slotHeaderInner?: React.ReactNode;
|
slotHeaderInner?: React.ReactNode;
|
||||||
slotFooter?: React.ReactNode;
|
slotFooter?: React.ReactNode;
|
||||||
|
withClose?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StyleProps = {
|
type StyleProps = {
|
||||||
@ -46,6 +47,7 @@ type StyleProps = {
|
|||||||
hasHeaderBorder?: boolean;
|
hasHeaderBorder?: boolean;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
withAnimation?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DialogProps = ElementProps & StyleProps;
|
export type DialogProps = ElementProps & StyleProps;
|
||||||
@ -79,9 +81,11 @@ export const Dialog = ({
|
|||||||
slotTrigger,
|
slotTrigger,
|
||||||
slotHeaderInner,
|
slotHeaderInner,
|
||||||
slotFooter,
|
slotFooter,
|
||||||
|
withClose = true,
|
||||||
placement = DialogPlacement.Default,
|
placement = DialogPlacement.Default,
|
||||||
portalContainer,
|
portalContainer,
|
||||||
hasHeaderBorder = false,
|
hasHeaderBorder = false,
|
||||||
|
withAnimation = false,
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
}: DialogProps) => {
|
}: DialogProps) => {
|
||||||
@ -105,6 +109,7 @@ export const Dialog = ({
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
$withAnimation={withAnimation}
|
||||||
>
|
>
|
||||||
<Styled.Header $withBorder={hasHeaderBorder}>
|
<Styled.Header $withBorder={hasHeaderBorder}>
|
||||||
<Styled.HeaderTopRow>
|
<Styled.HeaderTopRow>
|
||||||
@ -114,7 +119,7 @@ export const Dialog = ({
|
|||||||
|
|
||||||
{title && <Styled.Title>{title}</Styled.Title>}
|
{title && <Styled.Title>{title}</Styled.Title>}
|
||||||
|
|
||||||
{!preventClose && (
|
{!preventClose && withClose && (
|
||||||
<Styled.Close ref={closeButtonRef}>
|
<Styled.Close ref={closeButtonRef}>
|
||||||
<Icon iconName={IconName.Close} />
|
<Icon iconName={IconName.Close} />
|
||||||
</Styled.Close>
|
</Styled.Close>
|
||||||
@ -168,7 +173,7 @@ Styled.Overlay = styled(Overlay)`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Container = styled(Content)<{ placement: DialogPlacement }>`
|
Styled.Container = styled(Content)<{ placement: DialogPlacement; $withAnimation?: boolean }>`
|
||||||
/* Params */
|
/* Params */
|
||||||
--dialog-inset: 1rem;
|
--dialog-inset: 1rem;
|
||||||
--dialog-width: 30rem;
|
--dialog-width: 30rem;
|
||||||
@ -224,7 +229,7 @@ Styled.Container = styled(Content)<{ placement: DialogPlacement }>`
|
|||||||
|
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
${({ placement }) =>
|
${({ placement, $withAnimation }) =>
|
||||||
({
|
({
|
||||||
[DialogPlacement.Default]: css`
|
[DialogPlacement.Default]: css`
|
||||||
inset: var(--dialog-inset);
|
inset: var(--dialog-inset);
|
||||||
@ -260,9 +265,11 @@ Styled.Container = styled(Content)<{ placement: DialogPlacement }>`
|
|||||||
padding-bottom: var(--dialog-radius); */
|
padding-bottom: var(--dialog-radius); */
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
${$withAnimation &&
|
||||||
&[data-state='open'] {
|
css`
|
||||||
animation: ${keyframes`
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
&[data-state='open'] {
|
||||||
|
animation: ${keyframes`
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
@ -270,18 +277,19 @@ Styled.Container = styled(Content)<{ placement: DialogPlacement }>`
|
|||||||
max-height: 0;
|
max-height: 0;
|
||||||
}
|
}
|
||||||
`} 0.15s var(--ease-out-expo);
|
`} 0.15s var(--ease-out-expo);
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-state='closed'] {
|
&[data-state='closed'] {
|
||||||
animation: ${keyframes`
|
animation: ${keyframes`
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
scale: 0.9;
|
scale: 0.9;
|
||||||
max-height: 0;
|
max-height: 0;
|
||||||
}
|
}
|
||||||
`} 0.15s;
|
`} 0.15s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
`}
|
||||||
`,
|
`,
|
||||||
[DialogPlacement.Sidebar]: css`
|
[DialogPlacement.Sidebar]: css`
|
||||||
--dialog-width: var(--sidebar-width);
|
--dialog-width: var(--sidebar-width);
|
||||||
@ -291,50 +299,52 @@ Styled.Container = styled(Content)<{ placement: DialogPlacement }>`
|
|||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
${$withAnimation &&
|
||||||
&[data-state='open'] {
|
css`
|
||||||
animation: ${keyframes`
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
&[data-state='open'] {
|
||||||
|
animation: ${keyframes`
|
||||||
from {
|
from {
|
||||||
translate: 100% 0;
|
translate: 100% 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
`} 0.15s var(--ease-out-expo);
|
`} 0.15s var(--ease-out-expo);
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-state='closed'] {
|
&[data-state='closed'] {
|
||||||
animation: ${keyframes`
|
animation: ${keyframes`
|
||||||
to {
|
to {
|
||||||
translate: 100% 0;
|
translate: 100% 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
`} 0.15s var(--ease-out-expo);
|
`} 0.15s var(--ease-out-expo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
`}
|
||||||
`,
|
`,
|
||||||
[DialogPlacement.Inline]: css`
|
[DialogPlacement.Inline]: css`
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
${$withAnimation &&
|
||||||
&[data-state='open'] {
|
css`
|
||||||
animation: ${keyframes`
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
&[data-state='open'] {
|
||||||
|
animation: ${keyframes`
|
||||||
from {
|
from {
|
||||||
scale: 0.99;
|
scale: 0.99;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
/* filter: blur(2px); */
|
|
||||||
/* backdrop-filter: none; */
|
|
||||||
}
|
}
|
||||||
`} 0.15s var(--ease-out-expo);
|
`} 0.15s var(--ease-out-expo);
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-state='closed'] {
|
&[data-state='closed'] {
|
||||||
animation: ${keyframes`
|
animation: ${keyframes`
|
||||||
to {
|
to {
|
||||||
scale: 0.99;
|
scale: 0.99;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
/* filter: blur(2px); */
|
|
||||||
/* backdrop-filter: none; */
|
|
||||||
}
|
}
|
||||||
`} 0.15s var(--ease-out-expo);
|
`} 0.15s var(--ease-out-expo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
`}
|
||||||
`,
|
`,
|
||||||
[DialogPlacement.FullScreen]: css`
|
[DialogPlacement.FullScreen]: css`
|
||||||
--dialog-width: 100vw;
|
--dialog-width: 100vw;
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export const DiffArrowStory: Story<DiffArrowProps> = (args) => (
|
|||||||
|
|
||||||
DiffArrowStory.argTypes = {
|
DiffArrowStory.argTypes = {
|
||||||
direction: {
|
direction: {
|
||||||
options: ['left', 'right'],
|
options: ['left', 'right', 'up', 'down'],
|
||||||
control: { type: 'select' },
|
control: { type: 'select' },
|
||||||
defaultValue: 'right',
|
defaultValue: 'right',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -10,7 +10,7 @@ type ElementProps = {
|
|||||||
|
|
||||||
type StyleProps = {
|
type StyleProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
direction?: 'right' | 'left';
|
direction?: 'right' | 'left' | 'up' | 'down';
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DiffArrowProps = ElementProps & StyleProps;
|
export type DiffArrowProps = ElementProps & StyleProps;
|
||||||
@ -57,5 +57,11 @@ Styled.DiffArrowContainer = styled.span<DiffArrowProps>`
|
|||||||
left: css`
|
left: css`
|
||||||
transform: scaleX(-1);
|
transform: scaleX(-1);
|
||||||
`,
|
`,
|
||||||
|
up: css`
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
`,
|
||||||
|
down: css`
|
||||||
|
transform: rotate(90deg);
|
||||||
|
`,
|
||||||
}[direction || 'right'])}
|
}[direction || 'right'])}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -75,7 +75,7 @@ Styled.DiffValue = styled.div<{ hasInvalidNewValue?: boolean }>`
|
|||||||
${({ hasInvalidNewValue }) =>
|
${({ hasInvalidNewValue }) =>
|
||||||
hasInvalidNewValue &&
|
hasInvalidNewValue &&
|
||||||
css`
|
css`
|
||||||
color: var(--color-negative);
|
color: var(--color-error);
|
||||||
`}
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@ -33,9 +33,11 @@ export const DropdownHeaderMenu = <MenuItemValue extends string>({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Root>
|
<Root>
|
||||||
<Styled.Trigger className={className}>
|
<Styled.Trigger className={className} asChild>
|
||||||
{children}
|
<div>
|
||||||
<Styled.DropdownIconButton iconName={IconName.Caret} isToggle />
|
{children}
|
||||||
|
<Styled.DropdownIconButton iconName={IconName.Caret} isToggle />
|
||||||
|
</div>
|
||||||
</Styled.Trigger>
|
</Styled.Trigger>
|
||||||
<Portal>
|
<Portal>
|
||||||
<Styled.Content
|
<Styled.Content
|
||||||
@ -85,7 +87,7 @@ Styled.Trigger = styled(Trigger)`
|
|||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
:hover {
|
:hover {
|
||||||
filter: brightness(1.1);
|
filter: brightness(var(--hover-filter-base));
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@ -4,38 +4,43 @@ import { DropdownMenu } from '@/components/DropdownMenu';
|
|||||||
|
|
||||||
import { StoryWrapper } from '.ladle/components';
|
import { StoryWrapper } from '.ladle/components';
|
||||||
|
|
||||||
export const DropdownMenuStory: Story<Parameters<typeof DropdownMenu>> = (args) => {
|
export const DropdownMenuStory: Story<Parameters<typeof DropdownMenu>[0]> = (args) => {
|
||||||
const exampleItems = [
|
|
||||||
{
|
|
||||||
value: '1',
|
|
||||||
label: 'Item 1',
|
|
||||||
onSelect: () => alert('Item 1 action'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: '2',
|
|
||||||
label: 'Item 2',
|
|
||||||
onSelect: () => alert('Item 2 action'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: '3',
|
|
||||||
label: 'Item 3',
|
|
||||||
onSelect: () => alert('Item 3 action'),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<DropdownMenu
|
<DropdownMenu {...args}>
|
||||||
{...args}
|
|
||||||
items={exampleItems}
|
|
||||||
>
|
|
||||||
<span>Menu</span>
|
<span>Menu</span>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</StoryWrapper>
|
</StoryWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
DropdownMenuStory.args = {};
|
DropdownMenuStory.args = {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
value: '0',
|
||||||
|
label: 'Item 0',
|
||||||
|
onSelect: () => alert('Item 0 action'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '1',
|
||||||
|
label: 'Item 1 (accent)',
|
||||||
|
onSelect: () => alert('Item 1 action'),
|
||||||
|
highlightColor: 'accent',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '2',
|
||||||
|
label: 'Item 2 (create)',
|
||||||
|
onSelect: () => alert('Item 2 action'),
|
||||||
|
highlightColor: 'create',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '3',
|
||||||
|
label: 'Item 3 (destroy)',
|
||||||
|
onSelect: () => alert('Item 3 action'),
|
||||||
|
highlightColor: 'destroy',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
DropdownMenuStory.argTypes = {
|
DropdownMenuStory.argTypes = {
|
||||||
align: {
|
align: {
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export type DropdownMenuItem<T> = {
|
|||||||
label: React.ReactNode;
|
label: React.ReactNode;
|
||||||
onSelect?: () => void;
|
onSelect?: () => void;
|
||||||
separator?: boolean;
|
separator?: boolean;
|
||||||
highlightColor?: 'accent' | 'positive' | 'negative';
|
highlightColor?: 'accent' | 'create' | 'destroy';
|
||||||
};
|
};
|
||||||
|
|
||||||
type StyleProps = {
|
type StyleProps = {
|
||||||
@ -82,7 +82,7 @@ Styled.Separator = styled(Separator)`
|
|||||||
margin: 0.25rem 1rem;
|
margin: 0.25rem 1rem;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'positive' | 'negative' }>`
|
Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'create' | 'destroy' }>`
|
||||||
${popoverMixins.item}
|
${popoverMixins.item}
|
||||||
--item-font-size: var(--dropdownMenu-item-font-size);
|
--item-font-size: var(--dropdownMenu-item-font-size);
|
||||||
${({ $highlightColor }) =>
|
${({ $highlightColor }) =>
|
||||||
@ -90,11 +90,11 @@ Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'positive' | 'negative'
|
|||||||
['accent']: `
|
['accent']: `
|
||||||
--item-highlighted-textColor: var(--color-accent);
|
--item-highlighted-textColor: var(--color-accent);
|
||||||
`,
|
`,
|
||||||
['positive']: `
|
['create']: `
|
||||||
--item-highlighted-textColor: var(--color-positive);
|
--item-highlighted-textColor: var(--color-green);
|
||||||
`,
|
`,
|
||||||
['negative']: `
|
['destroy']: `
|
||||||
--item-highlighted-textColor: var(--color-negative);
|
--item-highlighted-textColor: var(--color-red);
|
||||||
`,
|
`,
|
||||||
}[$highlightColor])}
|
}[$highlightColor])}
|
||||||
|
|
||||||
|
|||||||
@ -28,21 +28,22 @@ const exampleItems = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const DropdownSelectMenuStory: Story<Parameters<typeof DropdownSelectMenu>> = (args) => {
|
export const DropdownSelectMenuStory: Story<
|
||||||
|
Pick<Parameters<typeof DropdownSelectMenu>[0], 'items' | 'align' | 'sideOffset' | 'disabled'>
|
||||||
|
> = (args) => {
|
||||||
const [item, setItem] = useState(exampleItems[0].value);
|
const [item, setItem] = useState(exampleItems[0].value);
|
||||||
return (
|
return (
|
||||||
<StoryWrapper>
|
<StoryWrapper>
|
||||||
<DropdownSelectMenu
|
<DropdownSelectMenu value={item} onValueChange={(value) => setItem(value)} {...args} />
|
||||||
items={exampleItems}
|
|
||||||
value={item}
|
|
||||||
onValueChange={(value) => setItem(value)}
|
|
||||||
{...args}
|
|
||||||
/>
|
|
||||||
</StoryWrapper>
|
</StoryWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
DropdownSelectMenuStory.args = {};
|
DropdownSelectMenuStory.args = {
|
||||||
|
items: exampleItems,
|
||||||
|
sideOffset: 1,
|
||||||
|
disabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
DropdownSelectMenuStory.argTypes = {
|
DropdownSelectMenuStory.argTypes = {
|
||||||
align: {
|
align: {
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import {
|
|||||||
RadioItem,
|
RadioItem,
|
||||||
Portal,
|
Portal,
|
||||||
} from '@radix-ui/react-dropdown-menu';
|
} from '@radix-ui/react-dropdown-menu';
|
||||||
|
import { CheckIcon } from '@radix-ui/react-icons';
|
||||||
|
|
||||||
import { type MenuItem } from '@/constants/menus';
|
import { type MenuItem } from '@/constants/menus';
|
||||||
|
|
||||||
@ -90,7 +91,9 @@ export const DropdownSelectMenu = <MenuItemValue extends string>({
|
|||||||
|
|
||||||
{slotAfter}
|
{slotAfter}
|
||||||
|
|
||||||
<Styled.ItemIndicator>✔{/* <CheckIcon /> */}</Styled.ItemIndicator>
|
<Styled.ItemIndicator>
|
||||||
|
<CheckIcon />
|
||||||
|
</Styled.ItemIndicator>
|
||||||
</Styled.RadioItem>
|
</Styled.RadioItem>
|
||||||
))}
|
))}
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
|
|||||||