Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4ef2b28fe | ||
|
|
7d65956cd0 | ||
|
|
27b79957d4 | ||
|
|
4bacc901dc | ||
|
|
82d32a91a9 | ||
|
|
2a794f9459 | ||
|
|
5c26a0c270 | ||
|
|
e4991cc31d | ||
|
|
da908c826a |
@@ -11,6 +11,7 @@
|
||||
## Prerequisites
|
||||
|
||||
- Node.js version 18 and `pnpm` installed on your system
|
||||
- Wallet Connect account
|
||||
|
||||
For deploying with Vercel, create an account with [Vercel](https://vercel.com/signup) if you don't have one already.
|
||||
|
||||
@@ -61,7 +62,14 @@ pnpm ladle
|
||||
|
||||
This will automatically open your default browser at `http://localhost:61000`.
|
||||
|
||||
## Part 3: Deploying with Vercel
|
||||
## Part 3: Configuring environment
|
||||
|
||||
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:
|
||||
- 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)
|
||||
|
||||
## Part 4: Deploying with Vercel
|
||||
|
||||
### Step 1: Connect your repository to Vercel
|
||||
|
||||
@@ -78,7 +86,7 @@ If you wish to incorporate analytics via Amplitude and Bugsnag, you can use our
|
||||
|
||||
For more details, check out Vercel's [official documentation](https://vercel.com/docs).
|
||||
|
||||
## Part 4: Deploying to IPFS
|
||||
## Part 5: Deploying to IPFS
|
||||
|
||||
### web3.storage: deploy to IPFS via web3.storage using the provided script
|
||||
|
||||
|
||||
+2
-2
@@ -38,8 +38,8 @@
|
||||
"@cosmjs/proto-signing": "^0.31.0",
|
||||
"@cosmjs/stargate": "^0.31.0",
|
||||
"@cosmjs/tendermint-rpc": "^0.31.0",
|
||||
"@dydxprotocol/v4-abacus": "^0.7.0",
|
||||
"@dydxprotocol/v4-client-js": "^0.36.1",
|
||||
"@dydxprotocol/v4-abacus": "^0.7.2",
|
||||
"@dydxprotocol/v4-client-js": "^0.40.3",
|
||||
"@dydxprotocol/v4-localization": "^0.1.30",
|
||||
"@ethersproject/providers": "^5.7.2",
|
||||
"@js-joda/core": "^5.5.3",
|
||||
|
||||
Generated
+21
-20
@@ -27,11 +27,11 @@ dependencies:
|
||||
specifier: ^0.31.0
|
||||
version: 0.31.0
|
||||
'@dydxprotocol/v4-abacus':
|
||||
specifier: ^0.7.0
|
||||
version: 0.7.0
|
||||
specifier: ^0.7.2
|
||||
version: 0.7.2
|
||||
'@dydxprotocol/v4-client-js':
|
||||
specifier: ^0.36.1
|
||||
version: 0.36.1
|
||||
specifier: ^0.40.3
|
||||
version: 0.40.3
|
||||
'@dydxprotocol/v4-localization':
|
||||
specifier: ^0.1.30
|
||||
version: 0.1.30
|
||||
@@ -645,7 +645,7 @@ packages:
|
||||
/@confio/ics23@0.6.8:
|
||||
resolution: {integrity: sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w==}
|
||||
dependencies:
|
||||
'@noble/hashes': 1.3.1
|
||||
'@noble/hashes': 1.3.2
|
||||
protobufjs: 6.11.4
|
||||
dev: false
|
||||
|
||||
@@ -717,7 +717,7 @@ packages:
|
||||
'@cosmjs/encoding': 0.30.1
|
||||
'@cosmjs/math': 0.30.1
|
||||
'@cosmjs/utils': 0.30.1
|
||||
'@noble/hashes': 1.3.1
|
||||
'@noble/hashes': 1.3.2
|
||||
bn.js: 5.2.1
|
||||
elliptic: 6.5.4
|
||||
libsodium-wrappers: 0.7.11
|
||||
@@ -979,12 +979,12 @@ packages:
|
||||
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
|
||||
dev: true
|
||||
|
||||
/@dydxprotocol/v4-abacus@0.7.0:
|
||||
resolution: {integrity: sha512-XheqfIpOODfQFG860oH0fneVgp9qQKPMDTwrvFXaM/JtKH9ekOUUO6De72EsJ7qOuxWwl1WgoALA8b4tRs0tiw==}
|
||||
/@dydxprotocol/v4-abacus@0.7.2:
|
||||
resolution: {integrity: sha512-5foamomN82FH6ko3EuzwFlSoAEY6Sal8fDgvZo2RsB19Ks6SFgFDeeOcEDdfoa3DNwvl8yW0C9cfxeQ+BfU8uA==}
|
||||
dev: false
|
||||
|
||||
/@dydxprotocol/v4-client-js@0.36.1:
|
||||
resolution: {integrity: sha512-KJ3MtWI61wmm+xZtXQd7/hYKIoVFG32TRdyyVaXXO8vpW9Oqd0JD8QSM/wuegkciAh5YmP/BrDzYuu77zHO6yg==}
|
||||
/@dydxprotocol/v4-client-js@0.40.3:
|
||||
resolution: {integrity: sha512-nMQd6tYisKDKIbfx0BGJSYEOSt+I+t5SsaBSmlgTdso+w2rCRO9vyxS+u6MF9h4w5FsVRfhHo3e6uTWX48WpGQ==}
|
||||
dependencies:
|
||||
'@cosmjs/amino': 0.30.1
|
||||
'@cosmjs/encoding': 0.31.1
|
||||
@@ -993,14 +993,15 @@ packages:
|
||||
'@cosmjs/stargate': 0.30.1
|
||||
'@cosmjs/tendermint-rpc': 0.30.1
|
||||
'@cosmjs/utils': 0.31.1
|
||||
'@dydxprotocol/v4-proto': 0.2.1
|
||||
'@dydxprotocol/v4-proto': 0.4.1
|
||||
'@osmonauts/lcd': 0.6.0
|
||||
'@scure/bip32': 1.3.1
|
||||
'@scure/bip32': 1.3.2
|
||||
'@scure/bip39': 1.2.1
|
||||
axios: 1.1.3
|
||||
bech32: 1.1.4
|
||||
bignumber.js: 9.1.1
|
||||
ethereum-cryptography: 2.1.2
|
||||
ethers: 6.6.1
|
||||
long: 4.0.0
|
||||
protobufjs: 6.11.4
|
||||
ws: 8.13.0(bufferutil@4.0.7)(utf-8-validate@5.0.10)
|
||||
@@ -1014,8 +1015,8 @@ packages:
|
||||
resolution: {integrity: sha512-xTlQuQmPz7wfGkjd07giYMAxRrolDbJE3DryJSIMB6R1MBq1wLzAcwp/iR/nELRwilRX9c44Tap0gGt+oAajiQ==}
|
||||
dev: false
|
||||
|
||||
/@dydxprotocol/v4-proto@0.2.1:
|
||||
resolution: {integrity: sha512-Q5b/g331DoyMjBpO2/jtrxUX3WF5UaIKZp/unK332xuefHNFnkMYtZ05p0V71iSdO35tBdz8yt0VYP2WtUsp+w==}
|
||||
/@dydxprotocol/v4-proto@0.4.1:
|
||||
resolution: {integrity: sha512-2pBkokufWcxfIpiXE6QuQOBXUe154OTp6ojCIdOPW9TFLxzchoygxXnb5dL6rAQVNj9Qbg+hhXBllutt4m99dw==}
|
||||
dependencies:
|
||||
protobufjs: 6.11.4
|
||||
dev: false
|
||||
@@ -4708,8 +4709,8 @@ packages:
|
||||
resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==}
|
||||
dependencies:
|
||||
'@noble/curves': 1.1.0
|
||||
'@noble/hashes': 1.3.1
|
||||
'@scure/base': 1.1.1
|
||||
'@noble/hashes': 1.3.2
|
||||
'@scure/base': 1.1.3
|
||||
dev: false
|
||||
|
||||
/@scure/bip32@1.3.2:
|
||||
@@ -4731,7 +4732,7 @@ packages:
|
||||
resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==}
|
||||
dependencies:
|
||||
'@noble/hashes': 1.3.2
|
||||
'@scure/base': 1.1.1
|
||||
'@scure/base': 1.1.3
|
||||
dev: false
|
||||
|
||||
/@solana/buffer-layout@4.0.1:
|
||||
@@ -4745,8 +4746,8 @@ packages:
|
||||
resolution: {integrity: sha512-up5VG1dK+GPhykmuMIozJZBbVqpm77vbOG6/r5dS7NBGZonwHfTLdBbsYc3rjmaQ4DpCXUa3tUc4RZHRORvZrw==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.10
|
||||
'@noble/curves': 1.1.0
|
||||
'@noble/hashes': 1.3.1
|
||||
'@noble/curves': 1.2.0
|
||||
'@noble/hashes': 1.3.2
|
||||
'@solana/buffer-layout': 4.0.1
|
||||
agentkeepalive: 4.5.0
|
||||
bigint-buffer: 1.1.5
|
||||
@@ -7144,7 +7145,7 @@ packages:
|
||||
/bip39@3.1.0:
|
||||
resolution: {integrity: sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==}
|
||||
dependencies:
|
||||
'@noble/hashes': 1.3.1
|
||||
'@noble/hashes': 1.3.2
|
||||
dev: false
|
||||
|
||||
/bl@5.1.0:
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
+16
-16
@@ -40,7 +40,7 @@
|
||||
"isMainNet": false,
|
||||
"tokens": {
|
||||
"chain": {
|
||||
"name": "DYDX",
|
||||
"name": "Dv4TNT",
|
||||
"denom": "adv4tnt",
|
||||
"decimals": 18,
|
||||
"image": "/currencies/dydx.png"
|
||||
@@ -100,7 +100,7 @@
|
||||
"isMainNet": false,
|
||||
"tokens": {
|
||||
"chain": {
|
||||
"name": "DYDX",
|
||||
"name": "Dv4TNT",
|
||||
"denom": "adv4tnt",
|
||||
"decimals": 18,
|
||||
"image": "/currencies/dydx.png"
|
||||
@@ -121,7 +121,7 @@
|
||||
}
|
||||
],
|
||||
"validators": [
|
||||
"http://35.75.227.118"
|
||||
"http://54.92.118.111"
|
||||
],
|
||||
"0xsquid": "https://testnet.api.0xsquid.com"
|
||||
},
|
||||
@@ -159,7 +159,7 @@
|
||||
"isMainNet": false,
|
||||
"tokens": {
|
||||
"chain": {
|
||||
"name": "DYDX",
|
||||
"name": "Dv4TNT",
|
||||
"denom": "adv4tnt",
|
||||
"decimals": 18,
|
||||
"image": "/currencies/dydx.png"
|
||||
@@ -218,7 +218,7 @@
|
||||
"isMainNet": false,
|
||||
"tokens": {
|
||||
"chain": {
|
||||
"name": "DYDX",
|
||||
"name": "Dv4TNT",
|
||||
"denom": "adv4tnt",
|
||||
"decimals": 18,
|
||||
"image": "/currencies/dydx.png"
|
||||
@@ -277,7 +277,7 @@
|
||||
"isMainNet": false,
|
||||
"tokens": {
|
||||
"chain": {
|
||||
"name": "DYDX",
|
||||
"name": "Dv4TNT",
|
||||
"denom": "adv4tnt",
|
||||
"decimals": 18,
|
||||
"image": "/currencies/dydx.png"
|
||||
@@ -340,7 +340,7 @@
|
||||
"isMainNet": false,
|
||||
"tokens": {
|
||||
"chain": {
|
||||
"name": "DYDX",
|
||||
"name": "Dv4TNT",
|
||||
"denom": "adv4tnt",
|
||||
"decimals": 18,
|
||||
"image": "/currencies/dydx.png"
|
||||
@@ -403,7 +403,7 @@
|
||||
"isMainNet": false,
|
||||
"tokens": {
|
||||
"chain": {
|
||||
"name": "DYDX",
|
||||
"name": "Dv4TNT",
|
||||
"denom": "adv4tnt",
|
||||
"decimals": 18,
|
||||
"image": "/currencies/dydx.png"
|
||||
@@ -468,7 +468,7 @@
|
||||
"isMainNet": false,
|
||||
"tokens": {
|
||||
"chain": {
|
||||
"name": "DYDX",
|
||||
"name": "Dv4TNT",
|
||||
"denom": "adv4tnt",
|
||||
"decimals": 18,
|
||||
"image": "/currencies/dydx.png"
|
||||
@@ -532,7 +532,7 @@
|
||||
"isMainNet": false,
|
||||
"tokens": {
|
||||
"chain": {
|
||||
"name": "DYDX",
|
||||
"name": "Dv4TNT",
|
||||
"denom": "adv4tnt",
|
||||
"decimals": 18,
|
||||
"image": "/currencies/dydx.png"
|
||||
@@ -596,7 +596,7 @@
|
||||
"isMainNet": false,
|
||||
"tokens": {
|
||||
"chain": {
|
||||
"name": "DYDX",
|
||||
"name": "Dv4TNT",
|
||||
"denom": "adv4tnt",
|
||||
"decimals": 18,
|
||||
"image": "/currencies/dydx.png"
|
||||
@@ -660,7 +660,7 @@
|
||||
"isMainNet": false,
|
||||
"tokens": {
|
||||
"chain": {
|
||||
"name": "DYDX",
|
||||
"name": "Dv4TNT",
|
||||
"denom": "adv4tnt",
|
||||
"decimals": 18,
|
||||
"image": "/currencies/dydx.png"
|
||||
@@ -724,7 +724,7 @@
|
||||
"isMainNet": false,
|
||||
"tokens": {
|
||||
"chain": {
|
||||
"name": "DYDX",
|
||||
"name": "Dv4TNT",
|
||||
"denom": "adv4tnt",
|
||||
"decimals": 18,
|
||||
"image": "/currencies/dydx.png"
|
||||
@@ -789,8 +789,8 @@
|
||||
"tokens": {
|
||||
"comment": "Change according to mainnet release",
|
||||
"chain": {
|
||||
"name": "DYDX",
|
||||
"denom": "adv4tnt",
|
||||
"name": "TokenName",
|
||||
"denom": "tokenDenom",
|
||||
"decimals": 18,
|
||||
"image": "/currencies/dydx.png"
|
||||
},
|
||||
@@ -844,4 +844,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-2
@@ -7,7 +7,13 @@ import { GrazProvider } from 'graz';
|
||||
|
||||
import { AppRoute, DEFAULT_TRADE_ROUTE } from '@/constants/routes';
|
||||
|
||||
import { useBreakpoints, useInitializePage, useShouldShowFooter, useAnalytics } from '@/hooks';
|
||||
import {
|
||||
useBreakpoints,
|
||||
useTokenConfigs,
|
||||
useInitializePage,
|
||||
useShouldShowFooter,
|
||||
useAnalytics,
|
||||
} from '@/hooks';
|
||||
import { DydxProvider } from '@/hooks/useDydxClient';
|
||||
import { AccountsProvider } from '@/hooks/useAccounts';
|
||||
import { DialogAreaProvider, useDialogArea } from '@/hooks/useDialogArea';
|
||||
@@ -27,6 +33,8 @@ 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 { FooterDesktop } from '@/layout/Footer/FooterDesktop';
|
||||
@@ -55,6 +63,7 @@ const Content = () => {
|
||||
const { isTablet, isNotTablet } = useBreakpoints();
|
||||
const isShowingHeader = isNotTablet;
|
||||
const isShowingFooter = useShouldShowFooter();
|
||||
const { chainTokenLabel } = useTokenConfigs();
|
||||
|
||||
return (
|
||||
<Styled.Content isShowingHeader={isShowingHeader} isShowingFooter={isShowingFooter}>
|
||||
@@ -69,7 +78,7 @@ const Content = () => {
|
||||
</Route>
|
||||
|
||||
<Route path={AppRoute.Markets} element={<MarketsPage />} />
|
||||
<Route path={AppRoute.Rewards} element={<RewardsPage />} />
|
||||
<Route path={`/${chainTokenLabel}`} element={<RewardsPage />} />
|
||||
{isTablet && (
|
||||
<>
|
||||
<Route path={AppRoute.Alerts} element={<AlertsPage />} />
|
||||
@@ -82,6 +91,9 @@ const Content = () => {
|
||||
<Route path={`${AppRoute.Portfolio}/*`} element={<PortfolioPage />} />
|
||||
</Route>
|
||||
|
||||
<Route path={AppRoute.Terms} element={<TermsOfUsePage />} />
|
||||
<Route path={AppRoute.Privacy} element={<PrivacyPolicyPage />} />
|
||||
|
||||
<Route path="*" element={<Navigate to={DEFAULT_TRADE_ROUTE} replace />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
|
||||
@@ -7,7 +7,8 @@ export enum AppRoute {
|
||||
Profile = '/profile',
|
||||
Alerts = '/alerts',
|
||||
Settings = '/settings',
|
||||
Rewards = '/DV4TNT',
|
||||
Terms = '/terms',
|
||||
Privacy = '/privacy',
|
||||
}
|
||||
|
||||
export enum PortfolioRoute {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ExternalProvider } from '@ethersproject/providers';
|
||||
import { USDC_DENOM, type onboarding, DYDX_DENOM } from '@dydxprotocol/v4-client-js';
|
||||
import { type onboarding } from '@dydxprotocol/v4-client-js';
|
||||
import type { suggestChain } from 'graz';
|
||||
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
@@ -352,15 +352,5 @@ export const DYDX_CHAIN_INFO: Parameters<typeof suggestChain>[0] = {
|
||||
// TODO: export this type from abacus instead
|
||||
export enum DydxChainAsset {
|
||||
USDC = 'usdc',
|
||||
DYDX = 'dydx',
|
||||
CHAINTOKEN = 'chain',
|
||||
}
|
||||
|
||||
export const DYDX_CHAIN_ASSET_COIN_DENOM: Record<DydxChainAsset, string> = {
|
||||
[DydxChainAsset.USDC]: USDC_DENOM,
|
||||
[DydxChainAsset.DYDX]: DYDX_DENOM,
|
||||
};
|
||||
|
||||
export const DYDX_CHAIN_ASSET_TAGS: Record<DydxChainAsset, string> = {
|
||||
[DydxChainAsset.USDC]: 'USDC',
|
||||
[DydxChainAsset.DYDX]: 'Dv4TNT',
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useApiState } from './useApiState';
|
||||
import { useBreakpoints } from './useBreakpoints';
|
||||
import { useTokenConfigs } from './useTokenConfigs';
|
||||
import { useCommandMenu } from './useCommandMenu';
|
||||
import { useCurrentMarketId } from './useCurrentMarketId';
|
||||
import { useDebounce } from './useDebounce';
|
||||
@@ -25,6 +26,7 @@ import { useSubaccount } from './useSubaccount';
|
||||
export {
|
||||
useApiState,
|
||||
useBreakpoints,
|
||||
useTokenConfigs,
|
||||
useCommandMenu,
|
||||
useCurrentMarketId,
|
||||
useDebounce,
|
||||
|
||||
@@ -5,8 +5,6 @@ import { StargateClient } from '@cosmjs/stargate';
|
||||
import { useQuery } from 'react-query';
|
||||
import { formatUnits } from 'viem';
|
||||
|
||||
import { USDC_DENOM, DYDX_DENOM } from '@dydxprotocol/v4-client-js';
|
||||
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
import { QUANTUM_MULTIPLIER } from '@/constants/numbers';
|
||||
import { EvmAddress } from '@/constants/wallets';
|
||||
@@ -18,6 +16,7 @@ import { getBalances, getStakingBalances } from '@/state/accountSelectors';
|
||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||
|
||||
import { useAccounts } from './useAccounts';
|
||||
import { useTokenConfigs } from './useTokenConfigs';
|
||||
|
||||
type UseAccountBalanceProps = {
|
||||
// Token Items
|
||||
@@ -52,6 +51,7 @@ export const useAccountBalance = ({
|
||||
|
||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||
const balances = useSelector(getBalances, shallowEqual);
|
||||
const { chainTokenDenom, usdcDenom } = useTokenConfigs();
|
||||
const evmChainId = Number(ENVIRONMENT_CONFIG_MAP[selectedNetwork].ethereumChainId);
|
||||
const stakingBalances = useSelector(getStakingBalances, shallowEqual);
|
||||
|
||||
@@ -93,18 +93,14 @@ export const useAccountBalance = ({
|
||||
const { formatted: evmBalance } = evmQuery.data || {};
|
||||
const balance = !assetSymbol ? '0' : isCosmosChain ? cosmosQuery.data : evmBalance;
|
||||
|
||||
const nativeTokenCoinBalance = balances?.[DYDX_DENOM];
|
||||
const nativeTokenBalance = MustBigNumber(nativeTokenCoinBalance?.amount)
|
||||
.div(QUANTUM_MULTIPLIER)
|
||||
.toNumber();
|
||||
const nativeTokenCoinBalance = balances?.[chainTokenDenom];
|
||||
const nativeTokenBalance = MustBigNumber(nativeTokenCoinBalance?.amount);
|
||||
|
||||
const usdcCoinBalance = balances?.[USDC_DENOM];
|
||||
const usdcBalance = MustBigNumber(usdcCoinBalance?.amount).div(QUANTUM_MULTIPLIER).toNumber();
|
||||
const usdcCoinBalance = balances?.[usdcDenom];
|
||||
const usdcBalance = MustBigNumber(usdcCoinBalance?.amount).toNumber();
|
||||
|
||||
const nativeStakingCoinBalanace = stakingBalances?.[DYDX_DENOM];
|
||||
const nativeStakingBalance = MustBigNumber(nativeStakingCoinBalanace?.amount)
|
||||
.div(QUANTUM_MULTIPLIER)
|
||||
.toNumber();
|
||||
const nativeStakingCoinBalanace = stakingBalances?.[chainTokenDenom];
|
||||
const nativeStakingBalance = MustBigNumber(nativeStakingCoinBalanace?.amount).toNumber();
|
||||
|
||||
return {
|
||||
balance,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useCallback, useContext, createContext, useEffect, useState, useMemo }
|
||||
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { AES, enc } from 'crypto-js';
|
||||
import { LocalWallet, USDC_DENOM, type Subaccount } from '@dydxprotocol/v4-client-js';
|
||||
import { LocalWallet, type Subaccount } from '@dydxprotocol/v4-client-js';
|
||||
|
||||
import { OnboardingGuard, OnboardingState, type EvmDerivedAddresses } from '@/constants/account';
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
@@ -130,16 +130,8 @@ const useAccountsContext = () => {
|
||||
// dYdX subaccounts
|
||||
const [dydxSubaccounts, setDydxSubaccounts] = useState<Subaccount[] | undefined>();
|
||||
|
||||
const { getAccountBalance, getSubaccounts } = useMemo(
|
||||
const { getSubaccounts } = useMemo(
|
||||
() => ({
|
||||
getAccountBalance: async ({
|
||||
dydxAddress,
|
||||
denom = USDC_DENOM,
|
||||
}: {
|
||||
dydxAddress: DydxAddress;
|
||||
denom?: string;
|
||||
}) => await compositeClient?.validatorClient.get.getAccountBalance(dydxAddress, denom),
|
||||
|
||||
getSubaccounts: async ({ dydxAddress }: { dydxAddress: DydxAddress }) => {
|
||||
try {
|
||||
const response = await compositeClient?.indexerClient.account.getSubaccounts(dydxAddress);
|
||||
@@ -326,7 +318,6 @@ const useAccountsContext = () => {
|
||||
disconnect,
|
||||
|
||||
// dydxClient Account methods
|
||||
getAccountBalance,
|
||||
getSubaccounts,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -15,6 +15,8 @@ import type { ResolutionString } from 'public/tradingview/charting_library';
|
||||
|
||||
import type { ConnectNetworkEvent, NetworkConfig } from '@/constants/abacus';
|
||||
import { type Candle, RESOLUTION_MAP } from '@/constants/candles';
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
import { DydxChainAsset } from '@/constants/wallets';
|
||||
|
||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||
|
||||
@@ -36,6 +38,7 @@ const useDydxClientContext = () => {
|
||||
// ------ Network ------ //
|
||||
|
||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||
const tokensConfigs = ENVIRONMENT_CONFIG_MAP[selectedNetwork].tokens;
|
||||
|
||||
const [networkConfig, setNetworkConfig] = useState<NetworkConfig>();
|
||||
|
||||
@@ -65,7 +68,14 @@ const useDydxClientContext = () => {
|
||||
new Network(
|
||||
selectedNetwork,
|
||||
new IndexerConfig(networkConfig.indexerUrl, networkConfig.websocketUrl),
|
||||
new ValidatorConfig(networkConfig.validatorUrl, networkConfig.chainId, {
|
||||
new ValidatorConfig(networkConfig.validatorUrl, networkConfig.chainId,
|
||||
{
|
||||
USDC_DENOM: tokensConfigs[DydxChainAsset.USDC].denom,
|
||||
USDC_DECIMALS: tokensConfigs[DydxChainAsset.USDC].decimals,
|
||||
USDC_GAS_DENOM: tokensConfigs[DydxChainAsset.USDC].gasDenom,
|
||||
CHAINTOKEN_DENOM: tokensConfigs[DydxChainAsset.CHAINTOKEN].denom,
|
||||
CHAINTOKEN_DECIMALS: tokensConfigs[DydxChainAsset.CHAINTOKEN].decimals,
|
||||
}, {
|
||||
broadcastPollIntervalMs: 3_000,
|
||||
broadcastTimeoutMs: 60_000,
|
||||
})
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
import { LocalStorageKey } from '@/constants/localStorage';
|
||||
import { DEFAULT_APP_ENVIRONMENT, DydxNetwork, ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
|
||||
@@ -9,7 +8,6 @@ import { useAccounts, useLocalStorage } from '@/hooks';
|
||||
|
||||
import { setSelectedNetwork } from '@/state/app';
|
||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||
import { openDialog } from '@/state/dialogs';
|
||||
|
||||
import { validateAgainstAvailableEnvironments } from '@/lib/network';
|
||||
|
||||
@@ -27,17 +25,6 @@ export const useSelectedNetwork = (): {
|
||||
validateFn: validateAgainstAvailableEnvironments,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
import.meta.env.MODE === 'production' &&
|
||||
ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId === 'dydx-testnet-4'
|
||||
) {
|
||||
dispatch(
|
||||
openDialog({ type: DialogTypes.ExchangeOffline, dialogProps: { preventClose: true } })
|
||||
);
|
||||
}
|
||||
}, [selectedNetwork]);
|
||||
|
||||
const switchNetwork = useCallback(
|
||||
(network: DydxNetwork) => {
|
||||
disconnect();
|
||||
|
||||
+22
-17
@@ -3,15 +3,10 @@ import { shallowEqual, useSelector, useDispatch } from 'react-redux';
|
||||
import type { Nullable } from '@dydxprotocol/v4-abacus';
|
||||
import Long from 'long';
|
||||
import type { IndexedTx } from '@cosmjs/stargate';
|
||||
import type { EncodeObject, Coin } from '@cosmjs/proto-signing';
|
||||
import type { EncodeObject } from '@cosmjs/proto-signing';
|
||||
import { Method } from '@cosmjs/tendermint-rpc';
|
||||
|
||||
import {
|
||||
type LocalWallet,
|
||||
SubaccountClient,
|
||||
DYDX_DENOM,
|
||||
USDC_DENOM,
|
||||
} from '@dydxprotocol/v4-client-js';
|
||||
import { type LocalWallet, SubaccountClient } from '@dydxprotocol/v4-client-js';
|
||||
|
||||
import type {
|
||||
AccountBalance,
|
||||
@@ -34,6 +29,7 @@ import { MustBigNumber } from '@/lib/numbers';
|
||||
import { log } from '@/lib/telemetry';
|
||||
|
||||
import { useAccounts } from './useAccounts';
|
||||
import { useTokenConfigs } from './useTokenConfigs';
|
||||
import { useDydxClient } from './useDydxClient';
|
||||
|
||||
type SubaccountContextType = ReturnType<typeof useSubaccountContext>;
|
||||
@@ -52,6 +48,7 @@ export const useSubaccount = () => useContext(SubaccountContext);
|
||||
|
||||
export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: LocalWallet }) => {
|
||||
const dispatch = useDispatch();
|
||||
const { usdcDenom } = useTokenConfigs();
|
||||
const { compositeClient, faucetClient } = useDydxClient();
|
||||
|
||||
const { getFaucetFunds } = useMemo(
|
||||
@@ -91,7 +88,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
}: {
|
||||
subaccountClient: SubaccountClient;
|
||||
amount: number;
|
||||
}) => await compositeClient?.withdrawFromSubaccount(subaccountClient, amount),
|
||||
}) => await compositeClient?.withdrawFromSubaccount(subaccountClient, amount.toString()),
|
||||
|
||||
transferFromSubaccountToAddress: async ({
|
||||
subaccountClient,
|
||||
@@ -134,12 +131,21 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
amount: number;
|
||||
recipient: string;
|
||||
}) =>
|
||||
await compositeClient?.validatorClient.post.sendToken(
|
||||
subaccountClient,
|
||||
recipient,
|
||||
DYDX_DENOM,
|
||||
Long.fromNumber(amount * QUANTUM_MULTIPLIER),
|
||||
await compositeClient?.validatorClient.post.send(
|
||||
subaccountClient.wallet,
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
const msg = compositeClient?.sendTokenMessage(
|
||||
subaccountClient.wallet,
|
||||
amount.toString(),
|
||||
recipient,
|
||||
);
|
||||
|
||||
resolve([msg]);
|
||||
}),
|
||||
false,
|
||||
compositeClient?.validatorClient?.post.defaultDydxGasPrice,
|
||||
undefined,
|
||||
Method.BroadcastTxCommit
|
||||
),
|
||||
|
||||
@@ -156,7 +162,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
|
||||
const transaction = JSON.parse(payload);
|
||||
|
||||
const msg = compositeClient.withdrawFromSubaccountMessage(subaccountClient, amount);
|
||||
const msg = compositeClient.withdrawFromSubaccountMessage(subaccountClient, amount.toString());
|
||||
const ibcMsg: EncodeObject = {
|
||||
typeUrl: transaction.msgTypeUrl,
|
||||
value: transaction.msg,
|
||||
@@ -210,7 +216,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
);
|
||||
|
||||
const balances = useSelector(getBalances, shallowEqual);
|
||||
const usdcCoinBalance = balances?.[USDC_DENOM];
|
||||
const usdcCoinBalance = balances?.[usdcDenom];
|
||||
|
||||
useEffect(() => {
|
||||
if (usdcCoinBalance) {
|
||||
@@ -247,8 +253,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
if (!subaccountClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (await (coinDenom === USDC_DENOM
|
||||
return (await (coinDenom === usdcDenom
|
||||
? transferFromSubaccountToAddress
|
||||
: transferNativeToken)({ subaccountClient, amount, recipient })) as IndexedTx;
|
||||
},
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
import { DydxChainAsset } from '@/constants/wallets';
|
||||
|
||||
import { useSelectedNetwork } from '@/hooks';
|
||||
|
||||
export const useTokenConfigs = (): {
|
||||
tokensConfigs: {
|
||||
[DydxChainAsset.USDC]: {
|
||||
denom: string;
|
||||
name: string;
|
||||
decimals: number;
|
||||
gasDenom?: string;
|
||||
},
|
||||
[DydxChainAsset.CHAINTOKEN]: {
|
||||
denom: string;
|
||||
name: string;
|
||||
decimals: number;
|
||||
gasDenom?: string;
|
||||
},
|
||||
};
|
||||
usdcDenom: string;
|
||||
usdcLabel: string;
|
||||
chainTokenDenom: string;
|
||||
chainTokenLabel: string;
|
||||
} => {
|
||||
const { selectedNetwork } = useSelectedNetwork();
|
||||
const tokensConfigs = ENVIRONMENT_CONFIG_MAP[selectedNetwork].tokens;
|
||||
|
||||
return {
|
||||
tokensConfigs,
|
||||
usdcDenom: tokensConfigs[DydxChainAsset.USDC].denom,
|
||||
usdcLabel: tokensConfigs[DydxChainAsset.USDC].name,
|
||||
chainTokenDenom: tokensConfigs[DydxChainAsset.CHAINTOKEN].denom,
|
||||
chainTokenLabel: tokensConfigs[DydxChainAsset.CHAINTOKEN].name,
|
||||
};
|
||||
};
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { LocalStorageKey } from '@/constants/localStorage';
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
|
||||
import {
|
||||
type DydxAddress,
|
||||
@@ -28,6 +30,8 @@ import {
|
||||
WalletType as CosmosWalletType,
|
||||
} from 'graz';
|
||||
|
||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||
|
||||
import { resolveWagmiConnector } from '@/lib/wagmi';
|
||||
import { getWalletConnection, parseWalletError } from '@/lib/wallet';
|
||||
import { log } from '@/lib/telemetry';
|
||||
@@ -84,6 +88,9 @@ export const useWalletConnection = () => {
|
||||
|
||||
// Wallet connection
|
||||
|
||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||
const walletConnectConfig = ENVIRONMENT_CONFIG_MAP[selectedNetwork].wallets.walletconnect;
|
||||
|
||||
const { connectAsync: connectWagmi } =
|
||||
walletType && walletConnectionType
|
||||
? useConnectWagmi({
|
||||
@@ -92,6 +99,7 @@ export const useWalletConnection = () => {
|
||||
walletConnection: {
|
||||
type: walletConnectionType,
|
||||
},
|
||||
walletConnectConfig,
|
||||
}),
|
||||
})
|
||||
: useConnectWagmi();
|
||||
@@ -127,6 +135,7 @@ export const useWalletConnection = () => {
|
||||
connector: resolveWagmiConnector({
|
||||
walletType,
|
||||
walletConnection,
|
||||
walletConnectConfig,
|
||||
}),
|
||||
});
|
||||
}
|
||||
@@ -217,7 +226,7 @@ export const useWalletConnection = () => {
|
||||
evmAddressWagmi,
|
||||
signerWagmi,
|
||||
publicClientWagmi,
|
||||
|
||||
|
||||
// Wallet connection (Cosmos)
|
||||
dydxAddress,
|
||||
dydxAddressGraz,
|
||||
|
||||
@@ -6,9 +6,10 @@ import { ButtonShape } from '@/constants/buttons';
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { AppRoute } from '@/constants/routes';
|
||||
import { useStringGetter } from '@/hooks';
|
||||
import { LogoShortIcon, BellStrokeIcon } from '@/icons';
|
||||
|
||||
import { useTokenConfigs, useStringGetter } from '@/hooks';
|
||||
|
||||
import { Icon, IconName } from '@/components/Icon';
|
||||
import { IconButton } from '@/components/IconButton';
|
||||
import { NavigationMenu } from '@/components/NavigationMenu';
|
||||
@@ -27,6 +28,7 @@ import { layoutMixins } from '@/styles/layoutMixins';
|
||||
export const HeaderDesktop = () => {
|
||||
const stringGetter = useStringGetter();
|
||||
const dispatch = useDispatch();
|
||||
const { chainTokenLabel } = useTokenConfigs();
|
||||
|
||||
const navItems = [
|
||||
{
|
||||
@@ -43,9 +45,9 @@ export const HeaderDesktop = () => {
|
||||
href: AppRoute.Trade,
|
||||
},
|
||||
{
|
||||
value: 'Dv4TNT',
|
||||
label: 'Dv4TNT',
|
||||
href: AppRoute.Rewards,
|
||||
value: chainTokenLabel,
|
||||
label: chainTokenLabel,
|
||||
href: `/${chainTokenLabel}`,
|
||||
},
|
||||
{
|
||||
value: 'PORTFOLIO',
|
||||
@@ -78,13 +80,13 @@ export const HeaderDesktop = () => {
|
||||
value: 'TERMS_OF_USE',
|
||||
slotBefore: <Icon iconName={IconName.File} />,
|
||||
label: stringGetter({ key: STRING_KEYS.TERMS_OF_USE }),
|
||||
href: 'https://dydx.exchange/terms',
|
||||
href: AppRoute.Terms,
|
||||
},
|
||||
{
|
||||
value: 'PRIVACY_POLICY',
|
||||
slotBefore: <Icon iconName={IconName.Privacy} />,
|
||||
label: stringGetter({ key: STRING_KEYS.PRIVACY_POLICY }),
|
||||
href: 'https://dydx.exchange/privacy',
|
||||
href: AppRoute.Privacy,
|
||||
},
|
||||
{
|
||||
value: 'HELP',
|
||||
|
||||
@@ -14,8 +14,6 @@ import {
|
||||
OrderSide,
|
||||
OrderTimeInForce,
|
||||
OrderExecution,
|
||||
DYDX_DENOM,
|
||||
GAS_PRICE_DYDX_DENOM,
|
||||
} from '@dydxprotocol/v4-client-js';
|
||||
|
||||
import {
|
||||
@@ -66,16 +64,37 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
||||
): Promise<void> {
|
||||
try {
|
||||
const parsedParams = paramsInJson ? JSON.parse(paramsInJson) : {};
|
||||
const { indexerUrl, websocketUrl, validatorUrl, chainId } = parsedParams;
|
||||
const {
|
||||
indexerUrl,
|
||||
websocketUrl,
|
||||
validatorUrl,
|
||||
chainId,
|
||||
USDC_DENOM,
|
||||
USDC_DECIMALS,
|
||||
USDC_GAS_DENOM,
|
||||
CHAINTOKEN_DENOM,
|
||||
CHAINTOKEN_DECIMALS,
|
||||
} = parsedParams;
|
||||
|
||||
const compositeClient = await CompositeClient.connect(
|
||||
new Network(
|
||||
chainId,
|
||||
new IndexerConfig(indexerUrl, websocketUrl),
|
||||
new ValidatorConfig(validatorUrl, chainId, {
|
||||
broadcastPollIntervalMs: 3_000,
|
||||
broadcastTimeoutMs: 60_000,
|
||||
})
|
||||
new ValidatorConfig(
|
||||
validatorUrl,
|
||||
chainId,
|
||||
{
|
||||
USDC_DENOM,
|
||||
USDC_DECIMALS,
|
||||
USDC_GAS_DENOM,
|
||||
CHAINTOKEN_DENOM,
|
||||
CHAINTOKEN_DECIMALS,
|
||||
},
|
||||
{
|
||||
broadcastPollIntervalMs: 3_000,
|
||||
broadcastTimeoutMs: 60_000,
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -204,13 +223,13 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
||||
params ?? {};
|
||||
|
||||
try {
|
||||
const tx = await this.compositeClient?.cancelOrder(
|
||||
const tx = await this.compositeClient?.cancelRawOrder(
|
||||
new SubaccountClient(this.localWallet, subaccountNumber),
|
||||
clientId,
|
||||
orderFlags,
|
||||
clobPairId,
|
||||
goodTilBlock ?? undefined,
|
||||
goodTilBlockTime ?? undefined
|
||||
goodTilBlock || undefined,
|
||||
goodTilBlockTime || undefined,
|
||||
);
|
||||
|
||||
const parsedTx = this.parseToPrimitives(tx);
|
||||
@@ -273,16 +292,18 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
||||
this.localWallet,
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
const msg = compositeClient?.validatorClient.post.composer.composeMsgSendToken(
|
||||
subaccountClient.address,
|
||||
if (!this.localWallet) {
|
||||
throw new Error('Missing compositeClient or localWallet');
|
||||
}
|
||||
const msg = compositeClient?.sendTokenMessage(
|
||||
this.localWallet,
|
||||
amount,
|
||||
recipient,
|
||||
DYDX_DENOM,
|
||||
Long.fromNumber(amount * QUANTUM_MULTIPLIER)
|
||||
);
|
||||
|
||||
resolve([msg]);
|
||||
}),
|
||||
GAS_PRICE_DYDX_DENOM
|
||||
this.compositeClient?.validatorClient?.post.defaultDydxGasPrice,
|
||||
);
|
||||
|
||||
const parsedTx = this.parseToPrimitives(tx);
|
||||
|
||||
+33
-13
@@ -95,15 +95,28 @@ const injectedConnectorOptions = {
|
||||
},
|
||||
};
|
||||
|
||||
const walletconnect2ConnectorOptions: ConstructorParameters<typeof WalletConnectConnector>[0] = {
|
||||
type WalletConnectConfig = {
|
||||
client: {
|
||||
name: string;
|
||||
description: string;
|
||||
iconUrl: string;
|
||||
};
|
||||
v2: {
|
||||
projectId: string;
|
||||
};
|
||||
};
|
||||
|
||||
const getWalletconnect2ConnectorOptions = (
|
||||
config: WalletConnectConfig
|
||||
): ConstructorParameters<typeof WalletConnectConnector>[0] => ({
|
||||
chains,
|
||||
options: {
|
||||
projectId: import.meta.env.VITE_WALLETCONNECT2_PROJECT_ID,
|
||||
projectId: config.v2.projectId,
|
||||
metadata: {
|
||||
name: 'dYdX',
|
||||
description: '',
|
||||
name: config.client.name,
|
||||
description: config.client.description,
|
||||
url: import.meta.env.VITE_BASE_URL,
|
||||
icons: [`${import.meta.env.VITE_BASE_URL}/cbw-image.png}`],
|
||||
icons: [config.client.iconUrl],
|
||||
},
|
||||
showQrModal: true,
|
||||
qrModalOptions: {
|
||||
@@ -115,9 +128,9 @@ const walletconnect2ConnectorOptions: ConstructorParameters<typeof WalletConnect
|
||||
explorerRecommendedWalletIds: WALLET_CONNECT_EXPLORER_RECOMMENDED_IDS,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const connectors = [
|
||||
const getConnectors = (walletConnectConfig: WalletConnectConfig) => [
|
||||
new MetaMaskConnector({
|
||||
chains,
|
||||
options: {
|
||||
@@ -131,7 +144,7 @@ const connectors = [
|
||||
reloadOnDisconnect: false,
|
||||
},
|
||||
}),
|
||||
new WalletConnectConnector(walletconnect2ConnectorOptions),
|
||||
new WalletConnectConnector(getWalletconnect2ConnectorOptions(walletConnectConfig)),
|
||||
new InjectedConnector(injectedConnectorOptions),
|
||||
];
|
||||
|
||||
@@ -153,27 +166,34 @@ const createInjectedConnectorWithProvider = (provider: ExternalProvider) =>
|
||||
provider as unknown as Awaited<ReturnType<InjectedConnector['getProvider']>>;
|
||||
})(injectedConnectorOptions) as InjectedConnector;
|
||||
|
||||
const createWalletConnect2ConnectorWithId = (walletconnect2Id: string) =>
|
||||
new WalletConnectConnector({
|
||||
const createWalletConnect2ConnectorWithId = (
|
||||
walletconnectId: string,
|
||||
walletConnectConfig: WalletConnectConfig
|
||||
) => {
|
||||
const walletconnect2ConnectorOptions = getWalletconnect2ConnectorOptions(walletConnectConfig);
|
||||
return new WalletConnectConnector({
|
||||
...walletconnect2ConnectorOptions,
|
||||
options: {
|
||||
...walletconnect2ConnectorOptions.options,
|
||||
qrModalOptions: {
|
||||
...walletconnect2ConnectorOptions.options.qrModalOptions,
|
||||
explorerRecommendedWalletIds: [walletconnect2Id],
|
||||
explorerRecommendedWalletIds: [walletconnectId],
|
||||
explorerExcludedWalletIds: 'ALL',
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Custom connector from wallet selection
|
||||
|
||||
export const resolveWagmiConnector = ({
|
||||
walletType,
|
||||
walletConnection,
|
||||
walletConnectConfig,
|
||||
}: {
|
||||
walletType: WalletType;
|
||||
walletConnection: WalletConnection;
|
||||
walletConnectConfig: WalletConnectConfig;
|
||||
}) => {
|
||||
const walletConfig = wallets[walletType];
|
||||
const walletConnectionConfig = walletConnectionTypes[walletConnection.type];
|
||||
@@ -181,6 +201,6 @@ export const resolveWagmiConnector = ({
|
||||
return walletConnection.type === WalletConnectionType.InjectedEip1193 && walletConnection.provider
|
||||
? createInjectedConnectorWithProvider(walletConnection.provider)
|
||||
: walletConnection.type === WalletConnectionType.WalletConnect2 && walletConfig.walletconnect2Id
|
||||
? createWalletConnect2ConnectorWithId(walletConfig.walletconnect2Id)
|
||||
: connectors.find(({ id }: { id: string }) => id === walletConnectionConfig.wagmiConnectorId);
|
||||
? createWalletConnect2ConnectorWithId(walletConfig.walletconnect2Id, walletConnectConfig)
|
||||
: getConnectors(walletConnectConfig).find(({ id }: { id: string }) => id === walletConnectionConfig.wagmiConnectorId);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import styled, { AnyStyledComponent } from 'styled-components';
|
||||
|
||||
import { articleMixins } from '@/styles/articleMixins';
|
||||
|
||||
export const PrivacyPolicyPage = () => (
|
||||
<Styled.Article>
|
||||
<header>
|
||||
<h1>Privacy Policy</h1>
|
||||
</header>
|
||||
</Styled.Article>
|
||||
);
|
||||
|
||||
const Styled: Record<string, AnyStyledComponent> = {};
|
||||
|
||||
Styled.Article = styled.article`
|
||||
${articleMixins.article}
|
||||
`;
|
||||
@@ -0,0 +1,17 @@
|
||||
import styled, { AnyStyledComponent } from 'styled-components';
|
||||
|
||||
import { articleMixins } from '@/styles/articleMixins';
|
||||
|
||||
export const TermsOfUsePage = () => (
|
||||
<Styled.Article>
|
||||
<header>
|
||||
<h1>Terms of Use</h1>
|
||||
</header>
|
||||
</Styled.Article>
|
||||
);
|
||||
|
||||
const Styled: Record<string, AnyStyledComponent> = {};
|
||||
|
||||
Styled.Article = styled.article`
|
||||
${articleMixins.article}
|
||||
`;
|
||||
@@ -3,7 +3,7 @@ import styled, { AnyStyledComponent } from 'styled-components';
|
||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
import { useAccountBalance, useAccounts, useStringGetter } from '@/hooks';
|
||||
import { useAccountBalance, useAccounts, useTokenConfigs, useStringGetter } from '@/hooks';
|
||||
|
||||
import { ButtonAction, ButtonSize } from '@/constants/buttons';
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
@@ -30,6 +30,7 @@ export const DYDXBalancePanel = () => {
|
||||
const { walletType } = useAccounts();
|
||||
const canAccountTrade = useSelector(calculateCanAccountTrade, shallowEqual);
|
||||
const { nativeTokenBalance, nativeStakingBalance } = useAccountBalance();
|
||||
const { chainTokenLabel } = useTokenConfigs();
|
||||
|
||||
return (
|
||||
<Panel
|
||||
@@ -37,7 +38,7 @@ export const DYDXBalancePanel = () => {
|
||||
<Styled.Header>
|
||||
<Styled.Title>
|
||||
{/* <AssetIcon symbol="DYDX" /> */}
|
||||
Dv4TNT
|
||||
{chainTokenLabel}
|
||||
</Styled.Title>
|
||||
<Styled.ReceiveAndTransferButtons>
|
||||
{!canAccountTrade ? (
|
||||
@@ -106,7 +107,13 @@ export const DYDXBalancePanel = () => {
|
||||
{
|
||||
key: 'totalBalance',
|
||||
label: 'Total balance',
|
||||
value: <Output type={OutputType.Asset} value={nativeTokenBalance + nativeStakingBalance} tag="Dv4TNT" />,
|
||||
value: (
|
||||
<Output
|
||||
type={OutputType.Asset}
|
||||
value={nativeTokenBalance + nativeStakingBalance}
|
||||
tag={chainTokenLabel}
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
@@ -174,7 +181,6 @@ Styled.WalletAndStakedBalance = styled(Details)`
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 0.5rem;
|
||||
|
||||
|
||||
> div {
|
||||
gap: 1rem;
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ export const dialogsSlice = createSlice({
|
||||
initialState,
|
||||
reducers: {
|
||||
openDialog: (state: DialogsState, action: PayloadAction<DialogInfo<DialogTypes>>) => {
|
||||
if (state.activeDialog?.type === action.payload.type) return;
|
||||
|
||||
if (state.activeDialog) {
|
||||
state.dialogQueue.push(action.payload);
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import {
|
||||
css,
|
||||
type FlattenInterpolation,
|
||||
type FlattenSimpleInterpolation,
|
||||
type ThemeProps,
|
||||
} from 'styled-components';
|
||||
|
||||
export const articleMixins: Record<
|
||||
string,
|
||||
FlattenSimpleInterpolation | FlattenInterpolation<ThemeProps<any>>
|
||||
> = {
|
||||
article: css`
|
||||
padding: 2rem;
|
||||
overflow-wrap: break-word;
|
||||
user-select: text;
|
||||
margin: 0 auto;
|
||||
width: 60rem;
|
||||
max-width: 100vw;
|
||||
|
||||
header {
|
||||
color: var(--color-text-0);
|
||||
margin-bottom: 2rem;
|
||||
|
||||
h1 {
|
||||
font: var(--font-extra-book);
|
||||
color: var(--color-text-2);
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font: var(--font-large-book);
|
||||
color: var(--color-text-2);
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
h3,
|
||||
strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
strong {
|
||||
color: var(--color-text-2);
|
||||
}
|
||||
|
||||
p {
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
`,
|
||||
};
|
||||
@@ -75,16 +75,14 @@ export const AccountInfoConnectedState = () => {
|
||||
<Styled.Header>
|
||||
<span>{stringGetter({ key: STRING_KEYS.ACCOUNT })}</span>
|
||||
<Styled.TransferButtons>
|
||||
{import.meta.env.MODE !== 'production' && (
|
||||
<Styled.Button
|
||||
state={{ isDisabled: !dydxAccounts }}
|
||||
onClick={() => dispatch(openDialog({ type: DialogTypes.Withdraw }))}
|
||||
shape={ButtonShape.Pill}
|
||||
size={ButtonSize.XSmall}
|
||||
>
|
||||
{stringGetter({ key: STRING_KEYS.WITHDRAW })}
|
||||
</Styled.Button>
|
||||
)}
|
||||
<Styled.Button
|
||||
state={{ isDisabled: !dydxAccounts }}
|
||||
onClick={() => dispatch(openDialog({ type: DialogTypes.Withdraw }))}
|
||||
shape={ButtonShape.Pill}
|
||||
size={ButtonSize.XSmall}
|
||||
>
|
||||
{stringGetter({ key: STRING_KEYS.WITHDRAW })}
|
||||
</Styled.Button>
|
||||
<Styled.Button
|
||||
state={{ isDisabled: !dydxAccounts }}
|
||||
onClick={() => dispatch(openDialog({ type: DialogTypes.Deposit }))}
|
||||
|
||||
@@ -32,12 +32,9 @@ export const DepositDialog = ({ setIsOpen }: ElementProps) => {
|
||||
>
|
||||
<Styled.Content>
|
||||
{showTestDeposit ? <TestnetDepositForm onDeposit={closeDialog} /> : <DepositForm />}
|
||||
{/* TODO TRCL-1693 - uncomment when deposit form is ready */}
|
||||
{import.meta.env.MODE !== 'production' && (
|
||||
<Styled.TextToggle onClick={() => setShowTestDeposit(!showTestDeposit)}>
|
||||
{showTestDeposit ? 'Show deposit form (Under Construction)' : 'Show test faucet'}
|
||||
</Styled.TextToggle>
|
||||
)}
|
||||
<Styled.TextToggle onClick={() => setShowTestDeposit(!showTestDeposit)}>
|
||||
{showTestDeposit ? 'Show deposit form (Under Construction)' : 'Show test faucet'}
|
||||
</Styled.TextToggle>
|
||||
</Styled.Content>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -5,8 +5,6 @@ import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||
import { AbacusApiStatus } from '@/constants/abacus';
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
import { UNICODE } from '@/constants/unicode';
|
||||
|
||||
import { useApiState, useStringGetter } from '@/hooks';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
@@ -32,16 +30,8 @@ export const ExchangeOfflineDialog = ({ preventClose, setIsOpen }: ElementProps)
|
||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||
const activeDialog = useSelector(getActiveDialog, shallowEqual);
|
||||
|
||||
const showOfflineMessage =
|
||||
import.meta.env.MODE === 'production' &&
|
||||
ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId === 'dydx-testnet-4';
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
activeDialog?.type === DialogTypes.ExchangeOffline &&
|
||||
status === AbacusApiStatus.NORMAL &&
|
||||
!showOfflineMessage
|
||||
) {
|
||||
if (activeDialog?.type === DialogTypes.ExchangeOffline && status === AbacusApiStatus.NORMAL) {
|
||||
dispatch(closeDialog());
|
||||
}
|
||||
}, [status, selectedNetwork]);
|
||||
@@ -54,16 +44,7 @@ export const ExchangeOfflineDialog = ({ preventClose, setIsOpen }: ElementProps)
|
||||
title={stringGetter({ key: STRING_KEYS.UNAVAILABLE })}
|
||||
>
|
||||
<Styled.Content>
|
||||
{showOfflineMessage ? (
|
||||
<>
|
||||
<p>Testnet is currently offline. Please check back!</p>
|
||||
<Styled.Link href="https://v4-teacher.vercel.app/testnets/schedule">
|
||||
{stringGetter({ key: STRING_KEYS.LEARN_MORE })} {UNICODE.ARROW_RIGHT}
|
||||
</Styled.Link>
|
||||
</>
|
||||
) : (
|
||||
<p>{statusErrorMessage}</p>
|
||||
)}
|
||||
<p>{statusErrorMessage}</p>
|
||||
{import.meta.env.MODE !== 'production' && <NetworkSelectMenu />}
|
||||
</Styled.Content>
|
||||
</Dialog>
|
||||
|
||||
@@ -2,6 +2,7 @@ import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
|
||||
import { useAccounts, useStringGetter } from '@/hooks';
|
||||
|
||||
import { AppRoute } from '@/constants/routes';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { ButtonAction } from '@/constants/buttons';
|
||||
|
||||
@@ -29,12 +30,12 @@ export const AcknowledgeTerms = ({ onContinue }: ElementProps) => {
|
||||
key: STRING_KEYS.LEGAL_UPDATES_DESCRIPTION,
|
||||
params: {
|
||||
TOU: (
|
||||
<Styled.Link href="https://dydx.exchange/v4-terms">
|
||||
<Styled.Link href={`/#${AppRoute.Terms}`}>
|
||||
{stringGetter({ key: STRING_KEYS.TERMS_OF_USE })}
|
||||
</Styled.Link>
|
||||
),
|
||||
PRIVACY_POLICY: (
|
||||
<Styled.Link href="https://dydx.exchange/privacy">
|
||||
<Styled.Link href={`/#${AppRoute.Privacy}`}>
|
||||
{stringGetter({ key: STRING_KEYS.PRIVACY_POLICY })}
|
||||
</Styled.Link>
|
||||
),
|
||||
|
||||
@@ -264,7 +264,6 @@ const Styled: Record<string, AnyStyledComponent> = {};
|
||||
|
||||
Styled.StatusCardsContainer = styled.div`
|
||||
display: grid;
|
||||
margin-top: 1rem;
|
||||
gap: 1rem;
|
||||
`;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { DydxChainAsset } from '@/constants/wallets';
|
||||
|
||||
import { formMixins } from '@/styles/formMixins';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
import { useAccounts, useStringGetter } from '@/hooks';
|
||||
import { useAccounts, useTokenConfigs, useStringGetter } from '@/hooks';
|
||||
|
||||
import { AssetIcon } from '@/components/AssetIcon';
|
||||
import { CopyButton } from '@/components/CopyButton';
|
||||
@@ -24,9 +24,10 @@ type ElementProps = {
|
||||
setIsOpen: (open: boolean) => void;
|
||||
};
|
||||
|
||||
export const ReceiveDialog = ({ selectedAsset = DydxChainAsset.DYDX, setIsOpen }: ElementProps) => {
|
||||
export const ReceiveDialog = ({ selectedAsset = DydxChainAsset.CHAINTOKEN, setIsOpen }: ElementProps) => {
|
||||
const stringGetter = useStringGetter();
|
||||
const { dydxAddress } = useAccounts();
|
||||
const { chainTokenLabel, usdcLabel } = useTokenConfigs();
|
||||
|
||||
const [asset, setAsset] = useState(selectedAsset);
|
||||
|
||||
@@ -35,16 +36,17 @@ export const ReceiveDialog = ({ selectedAsset = DydxChainAsset.DYDX, setIsOpen }
|
||||
value: DydxChainAsset.USDC,
|
||||
label: (
|
||||
<Styled.InlineRow>
|
||||
<AssetIcon symbol="USDC" /> USDC
|
||||
<AssetIcon symbol="USDC" /> {usdcLabel}
|
||||
</Styled.InlineRow>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: DydxChainAsset.DYDX,
|
||||
value: DydxChainAsset.CHAINTOKEN,
|
||||
label: (
|
||||
<Styled.InlineRow>
|
||||
{/* TODO: conditionally display the native token assetIcon */}
|
||||
{/* <AssetIcon symbol="DYDX" /> */}
|
||||
Dv4TNT
|
||||
{chainTokenLabel}
|
||||
</Styled.InlineRow>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -11,11 +11,7 @@ import { ButtonShape, ButtonSize } from '@/constants/buttons';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
import { NumberSign } from '@/constants/numbers';
|
||||
import {
|
||||
DYDX_CHAIN_ASSET_COIN_DENOM,
|
||||
DYDX_CHAIN_ASSET_TAGS,
|
||||
DydxChainAsset,
|
||||
} from '@/constants/wallets';
|
||||
import { DydxChainAsset } from '@/constants/wallets';
|
||||
|
||||
import {
|
||||
useAccountBalance,
|
||||
@@ -25,6 +21,7 @@ import {
|
||||
useSelectedNetwork,
|
||||
useStringGetter,
|
||||
useSubaccount,
|
||||
useTokenConfigs,
|
||||
} from '@/hooks';
|
||||
|
||||
import { formMixins } from '@/styles/formMixins';
|
||||
@@ -57,7 +54,7 @@ type TransferFormProps = {
|
||||
};
|
||||
|
||||
export const TransferForm = ({
|
||||
selectedAsset = DydxChainAsset.DYDX,
|
||||
selectedAsset = DydxChainAsset.CHAINTOKEN,
|
||||
onDone,
|
||||
className,
|
||||
}: TransferFormProps) => {
|
||||
@@ -72,6 +69,7 @@ export const TransferForm = ({
|
||||
const { transfer } = useSubaccount();
|
||||
const { nativeTokenBalance, usdcBalance } = useAccountBalance();
|
||||
const { selectedNetwork } = useSelectedNetwork();
|
||||
const { tokensConfigs, usdcLabel, chainTokenLabel } = useTokenConfigs();
|
||||
|
||||
// User Input
|
||||
const [asset, setAsset] = useState<DydxChainAsset>(selectedAsset);
|
||||
@@ -138,7 +136,7 @@ export const TransferForm = ({
|
||||
try {
|
||||
// Subtract fees from amount if sending native tokens
|
||||
const amountToTransfer = (
|
||||
asset === DydxChainAsset.DYDX ? amountBN.minus(fee) : amountBN
|
||||
asset === DydxChainAsset.CHAINTOKEN ? amountBN.minus(fee) : amountBN
|
||||
).toNumber();
|
||||
|
||||
const screenResults = await screenAddresses({
|
||||
@@ -161,7 +159,7 @@ export const TransferForm = ({
|
||||
const txResponse = await transfer(
|
||||
amountToTransfer,
|
||||
recipientAddress as string,
|
||||
DYDX_CHAIN_ASSET_COIN_DENOM[asset]
|
||||
tokensConfigs[asset].denom,
|
||||
);
|
||||
|
||||
if (txResponse?.code === 0) {
|
||||
@@ -220,16 +218,16 @@ export const TransferForm = ({
|
||||
value: DydxChainAsset.USDC,
|
||||
label: (
|
||||
<Styled.InlineRow>
|
||||
<AssetIcon symbol="USDC" /> {DYDX_CHAIN_ASSET_TAGS[DydxChainAsset.USDC]}
|
||||
<AssetIcon symbol="USDC" /> {usdcLabel}
|
||||
</Styled.InlineRow>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: DydxChainAsset.DYDX,
|
||||
value: DydxChainAsset.CHAINTOKEN,
|
||||
label: (
|
||||
<Styled.InlineRow>
|
||||
{/* <AssetIcon symbol="DYDX" /> */}
|
||||
{DYDX_CHAIN_ASSET_TAGS[DydxChainAsset.DYDX]}
|
||||
{chainTokenLabel}
|
||||
</Styled.InlineRow>
|
||||
),
|
||||
},
|
||||
@@ -251,7 +249,7 @@ export const TransferForm = ({
|
||||
key: 'amount',
|
||||
label: (
|
||||
<span>
|
||||
{stringGetter({ key: STRING_KEYS.AVAILABLE })} <Tag>{DYDX_CHAIN_ASSET_TAGS[asset]}</Tag>
|
||||
{stringGetter({ key: STRING_KEYS.AVAILABLE })} <Tag>{tokensConfigs[asset].name}</Tag>
|
||||
</span>
|
||||
),
|
||||
value: (
|
||||
|
||||
@@ -3,9 +3,9 @@ import { shallowEqual, useSelector } from 'react-redux';
|
||||
import { ButtonAction, ButtonSize, ButtonType } from '@/constants/buttons';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { NumberSign } from '@/constants/numbers';
|
||||
import { DYDX_CHAIN_ASSET_TAGS, DydxChainAsset } from '@/constants/wallets';
|
||||
import { DydxChainAsset } from '@/constants/wallets';
|
||||
|
||||
import { useAccountBalance, useStringGetter } from '@/hooks';
|
||||
import { useAccountBalance, useTokenConfigs, useStringGetter } from '@/hooks';
|
||||
|
||||
import { Button } from '@/components/Button';
|
||||
import { DiffOutput } from '@/components/DiffOutput';
|
||||
@@ -37,6 +37,7 @@ export const TransferButtonAndReceipt = ({
|
||||
const stringGetter = useStringGetter();
|
||||
const canAccountTrade = useSelector(calculateCanAccountTrade, shallowEqual);
|
||||
const { size } = useSelector(getTransferInputs, shallowEqual) || {};
|
||||
const { tokensConfigs } = useTokenConfigs();
|
||||
|
||||
const { equity: equityInfo, leverage: leverageInfo } =
|
||||
useSelector(getSubaccount, shallowEqual) || {};
|
||||
@@ -60,7 +61,7 @@ export const TransferButtonAndReceipt = ({
|
||||
key: 'fees',
|
||||
label: (
|
||||
<span>
|
||||
{stringGetter({ key: STRING_KEYS.FEES })} <Tag>{DYDX_CHAIN_ASSET_TAGS[selectedAsset]}</Tag>
|
||||
{stringGetter({ key: STRING_KEYS.FEES })} <Tag>{tokensConfigs[selectedAsset].name}</Tag>
|
||||
</span>
|
||||
),
|
||||
value: <Output type={OutputType.Asset} value={fees} />,
|
||||
@@ -69,7 +70,7 @@ export const TransferButtonAndReceipt = ({
|
||||
key: 'balance',
|
||||
label: (
|
||||
<span>
|
||||
{stringGetter({ key: STRING_KEYS.BALANCE })} <Tag>{DYDX_CHAIN_ASSET_TAGS[selectedAsset]}</Tag>
|
||||
{stringGetter({ key: STRING_KEYS.BALANCE })} <Tag>{tokensConfigs[selectedAsset].name}</Tag>
|
||||
</span>
|
||||
),
|
||||
value: (
|
||||
|
||||
@@ -9,7 +9,13 @@ import { DialogTypes } from '@/constants/dialogs';
|
||||
import { STRING_KEYS, TOOLTIP_STRING_KEYS } from '@/constants/localization';
|
||||
import { DydxChainAsset, wallets } from '@/constants/wallets';
|
||||
|
||||
import { useAccounts, useBreakpoints, useStringGetter, useAccountBalance } from '@/hooks';
|
||||
import {
|
||||
useAccounts,
|
||||
useBreakpoints,
|
||||
useTokenConfigs,
|
||||
useStringGetter,
|
||||
useAccountBalance,
|
||||
} from '@/hooks';
|
||||
|
||||
import { OnboardingTriggerButton } from '@/views/dialogs/OnboardingTriggerButton';
|
||||
|
||||
@@ -39,6 +45,7 @@ export const AccountMenu = () => {
|
||||
const onboardingState = useSelector(getOnboardingState);
|
||||
const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {};
|
||||
const { nativeTokenBalance } = useAccountBalance();
|
||||
const { usdcLabel, chainTokenLabel } = useTokenConfigs();
|
||||
|
||||
const { evmAddress, walletType, dydxAddress, hdKey } = useAccounts();
|
||||
|
||||
@@ -107,17 +114,23 @@ export const AccountMenu = () => {
|
||||
<div>
|
||||
<div>
|
||||
<Styled.label>
|
||||
{stringGetter({ key: STRING_KEYS.ASSET_BALANCE, params: { ASSET: 'Dv4TNT' } })}
|
||||
{stringGetter({
|
||||
key: STRING_KEYS.ASSET_BALANCE,
|
||||
params: { ASSET: chainTokenLabel },
|
||||
})}
|
||||
{/* <AssetIcon symbol="DYDX" /> */}
|
||||
</Styled.label>
|
||||
<Styled.BalanceOutput type={OutputType.Asset} value={nativeTokenBalance} />
|
||||
</div>
|
||||
<AssetActions asset={DydxChainAsset.DYDX} dispatch={dispatch} />
|
||||
<AssetActions asset={DydxChainAsset.CHAINTOKEN} dispatch={dispatch} />
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<Styled.label>
|
||||
{stringGetter({ key: STRING_KEYS.ASSET_BALANCE, params: { ASSET: 'USDC' } })}
|
||||
{stringGetter({
|
||||
key: STRING_KEYS.ASSET_BALANCE,
|
||||
params: { ASSET: usdcLabel },
|
||||
})}
|
||||
<AssetIcon symbol="USDC" />
|
||||
</Styled.label>
|
||||
<Styled.BalanceOutput
|
||||
|
||||
Reference in New Issue
Block a user