diff --git a/package.json b/package.json index 02f58af..b0998e4 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,10 @@ "@cosmjs/encoding": "^0.31.0", "@cosmjs/proto-signing": "^0.31.0", "@cosmjs/stargate": "^0.31.0", - "@dydxprotocol/abacus": "^0.3.7", "@cosmjs/tendermint-rpc": "^0.31.0", + "@dydxprotocol/abacus": "^0.3.9", "@dydxprotocol/v4-client": "^0.29.0", + "@dydxprotocol/v4-localization": "^0.0.12", "@ethersproject/providers": "^5.7.2", "@js-joda/core": "^5.5.3", "@radix-ui/react-collapsible": "^1.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1345e6e..9c97876 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,11 +27,14 @@ dependencies: specifier: ^0.31.0 version: 0.31.0 '@dydxprotocol/abacus': - specifier: ^0.3.7 - version: 0.3.7 + specifier: ^0.3.9 + version: 0.3.9 '@dydxprotocol/v4-client': specifier: ^0.29.0 version: 0.29.0 + '@dydxprotocol/v4-localization': + specifier: ^0.0.12 + version: 0.0.12 '@ethersproject/providers': specifier: ^5.7.2 version: 5.7.2 @@ -1143,8 +1146,8 @@ packages: resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==} dev: true - /@dydxprotocol/abacus@0.3.7: - resolution: {integrity: sha512-wYGdsFNnVulwVqsNpMrS3j02lOyw/qg5QrB2DdlWtj4YeNZqvdM/vHC6HgU+U4McdVJW4STiEKW2Fl0rF/qbhQ==} + /@dydxprotocol/abacus@0.3.9: + resolution: {integrity: sha512-VphzsCEP5Apu41ln7Bi8+QwWBO1AuUZ4Fv02b7pPKw/BIy1eDW73FsC4qhyKW3KxQm/wo0X4Huom7r820KoR1A==} dev: false /@dydxprotocol/dydxjs@0.3.0: @@ -1187,6 +1190,10 @@ packages: - utf-8-validate dev: false + /@dydxprotocol/v4-localization@0.0.12: + resolution: {integrity: sha512-J5VY8WIIl/1/COO43E/wR/TYlEEjpydmTtUC4d02qhvRYip7m82TyqIMA9iiMvvCQnzY8RTNsHcvTb+puyGiQA==} + dev: false + /@emotion/is-prop-valid@1.2.1: resolution: {integrity: sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==} dependencies: diff --git a/src/constants/networks.tsx b/src/constants/networks.tsx index 87cae59..b17bcda 100644 --- a/src/constants/networks.tsx +++ b/src/constants/networks.tsx @@ -1,3 +1,13 @@ +import { ENDPOINTS, DEV_ENDPOINTS } from '@dydxprotocol/v4-localization'; + +const endpoints = import.meta.env.MODE === 'production' ? ENDPOINTS : DEV_ENDPOINTS; + +export const CLIENT_NETWORK_CONFIGS: Record = + Object.fromEntries( + endpoints.environments.map((environment) => [environment.environment, environment]) + ); +export const DEFAULT_APP_ENVIRONMENT = endpoints.defaultEnvironment; + export enum DydxV4Network { V4Mainnet = 'dydxprotocol-mainnet', V4Staging = 'dydxprotocol-staging', @@ -5,69 +15,12 @@ export enum DydxV4Network { V4Local = 'dydxprotocol-dev', } -export enum DydxV3Network { - V3Mainnet = '1', - V3Testnet = '5', -} +export type DydxNetwork = keyof typeof CLIENT_NETWORK_CONFIGS; -export function isDydxV4Network(network: any): network is DydxV4Network { - return Object.values(DydxV4Network).includes(network); +export function isDydxV4Network(network: any): boolean { + return CLIENT_NETWORK_CONFIGS[network]?.version === 'v4'; } export function isValidDydxNetwork(network: any): boolean { - return isDydxV4Network(network) || Object.values(DydxV3Network).includes(network); + return Object.keys(CLIENT_NETWORK_CONFIGS).includes(network); } - -export type DydxNetwork = DydxV4Network | DydxV3Network; - -export const CHAIN_IDS = { - [DydxV4Network.V4Mainnet]: '', - [DydxV4Network.V4Staging]: 'dydxprotocol-testnet', - [DydxV4Network.V4Testnet2]: 'dydx-testnet-2', - [DydxV4Network.V4Local]: 'dydxprotocol-testnet', - [DydxV3Network.V3Mainnet]: '1', - [DydxV3Network.V3Testnet]: '5', -}; - -export const DEFAULT_APP_ENVIRONMENT = - import.meta.env.MODE === 'production' ? DydxV4Network.V4Testnet2 : DydxV4Network.V4Staging; - -export const CLIENT_NETWORK_CONFIGS: Record< - DydxV4Network, - { - chainId: string; - validatorUrl: string; - faucetUrl: string; - indexerUrl: string; - ethereumChainId: number; - } -> = { - [DydxV4Network.V4Mainnet]: { - chainId: CHAIN_IDS[DydxV4Network.V4Mainnet], - validatorUrl: import.meta.env.VITE_VALIDATOR_URL_STAGE, - faucetUrl: import.meta.env.VITE_FAUCET_URL_STAGE, - indexerUrl: import.meta.env.VITE_INDEXER_URL_STAGE, - ethereumChainId: 1, - }, - [DydxV4Network.V4Local]: { - chainId: CHAIN_IDS[DydxV4Network.V4Local], - validatorUrl: import.meta.env.VITE_VALIDATOR_URL_DEV, - faucetUrl: import.meta.env.VITE_FAUCET_URL_DEV, - indexerUrl: import.meta.env.VITE_INDEXER_URL_DEV, - ethereumChainId: 5, - }, - [DydxV4Network.V4Staging]: { - chainId: CHAIN_IDS[DydxV4Network.V4Staging], - validatorUrl: import.meta.env.VITE_VALIDATOR_URL_STAGE, - faucetUrl: import.meta.env.VITE_FAUCET_URL_STAGE, - indexerUrl: import.meta.env.VITE_INDEXER_URL_STAGE, - ethereumChainId: 5, - }, - [DydxV4Network.V4Testnet2]: { - chainId: CHAIN_IDS[DydxV4Network.V4Testnet2], - validatorUrl: import.meta.env.VITE_VALIDATOR_URL_TESTNET2, - faucetUrl: import.meta.env.VITE_FAUCET_URL_TESTNET2, - indexerUrl: import.meta.env.VITE_INDEXER_URL_TESTNET2, - ethereumChainId: 5, - }, -}; diff --git a/src/hooks/useAccountBalance.ts b/src/hooks/useAccountBalance.ts index 1885b90..c649ec8 100644 --- a/src/hooks/useAccountBalance.ts +++ b/src/hooks/useAccountBalance.ts @@ -5,7 +5,7 @@ import { StargateClient } from '@cosmjs/stargate'; import { useQuery } from 'react-query'; import { formatUnits } from 'ethers'; -import { CLIENT_NETWORK_CONFIGS, type DydxV4Network } from '@/constants/networks'; +import { CLIENT_NETWORK_CONFIGS } from '@/constants/networks'; import { QUANTUM_MULTIPLIER } from '@/constants/numbers'; import { EthereumAddress } from '@/constants/wallets'; @@ -15,7 +15,6 @@ import { MustBigNumber } from '@/lib/numbers'; import { getSelectedNetwork } from '@/state/appSelectors'; import { useAccounts } from './useAccounts'; -// import { useDydxClient } from './useDydxClient'; import { usePollNativeTokenBalance } from './usePollNativeTokenBalance'; type UseAccountBalanceProps = { @@ -49,10 +48,8 @@ export const useAccountBalance = ({ }: UseAccountBalanceProps = {}) => { const { evmAddress, dydxAddress } = useAccounts(); - // TODO: let Abacus / useDydxClient handle EVM chain IDs - // const { networkConfig } = useDydxClient(); const selectedNetwork = useSelector(getSelectedNetwork); - const evmChainId = Number(CLIENT_NETWORK_CONFIGS[selectedNetwork as DydxV4Network].ethereumChainId); + const evmChainId = Number(CLIENT_NETWORK_CONFIGS[selectedNetwork].ethereumChainId); const evmQuery = useBalance({ enabled: Boolean(!isCosmosChain && addressOrDenom?.startsWith('0x')), diff --git a/src/hooks/useDisplayedWallets.ts b/src/hooks/useDisplayedWallets.ts index c060e0c..618ad45 100644 --- a/src/hooks/useDisplayedWallets.ts +++ b/src/hooks/useDisplayedWallets.ts @@ -1,4 +1,4 @@ -import { DydxV4Network } from '@/constants/networks'; +import { isDydxV4Network } from '@/constants/networks'; import { WalletType } from '@/constants/wallets'; import { isTruthy } from '@/lib/isTruthy'; @@ -11,9 +11,7 @@ export const useDisplayedWallets = () => { return [ WalletType.MetaMask, - import.meta.env.MODE !== 'production' && - [DydxV4Network.V4Testnet2, DydxV4Network.V4Staging].includes(selectedNetwork) && - WalletType.Keplr, + import.meta.env.MODE !== 'production' && isDydxV4Network(selectedNetwork) && WalletType.Keplr, WalletType.WalletConnect2, WalletType.WalletConnect, diff --git a/src/hooks/useSelectedNetwork.ts b/src/hooks/useSelectedNetwork.ts index 2f63c16..ca4cbb0 100644 --- a/src/hooks/useSelectedNetwork.ts +++ b/src/hooks/useSelectedNetwork.ts @@ -1,8 +1,8 @@ -import { useCallback, useEffect } from 'react'; +import { useCallback } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { LocalStorageKey } from '@/constants/localStorage'; -import { DEFAULT_APP_ENVIRONMENT, DydxNetwork, DydxV4Network } from '@/constants/networks'; +import { DEFAULT_APP_ENVIRONMENT, DydxNetwork } from '@/constants/networks'; import { useAccounts, useLocalStorage } from '@/hooks'; diff --git a/src/lib/abacus/filesystem.ts b/src/lib/abacus/filesystem.ts index 7c1e127..7404f7b 100644 --- a/src/lib/abacus/filesystem.ts +++ b/src/lib/abacus/filesystem.ts @@ -1,11 +1,12 @@ import type { AbacusFileSystemProtocol, FileLocation, Nullable } from '@/constants/abacus'; +import { DEV_ENDPOINTS, ENDPOINTS } from '@dydxprotocol/v4-localization'; class AbacusFileSystem implements AbacusFileSystemProtocol { readTextFile(location: FileLocation, path: string): Nullable { console.log({ location, path }); if (path === 'config/staging/environments.json') { - console.log('ENVIRONMENT_CONFIGS', globalThis.ENVIRONMENT_CONFIGS); - return JSON.stringify(globalThis.ENVIRONMENT_CONFIGS); + const environments = import.meta.env.MODE === 'production' ? ENDPOINTS : DEV_ENDPOINTS; + return JSON.stringify(environments); } return null; diff --git a/src/localization/en/app.json b/src/localization/en/app.json index a492d6b..dae35a8 100644 --- a/src/localization/en/app.json +++ b/src/localization/en/app.json @@ -1207,5 +1207,19 @@ "NODE_DOWN": "Node cannot be reached.", "NODE_HALTED": "Node has halted on block {BLOCK_NUMBER}.", "UNKNOWN_API_ERROR": "Unknown API error" + }, + "CHAIN": { + "V3_MAINNET": "V3 Mainnet", + "V3_GOERLI": "V3 Staging", + "V4_DEVNET": "V4 Dev 1", + "V4_DEVNET_2": "V4 Dev 2", + "V4_DEVNET_3": "V4 Dev 3", + "V4_DEVNET_4": "V4 Dev 4", + "V4_DEVNET_5": "V4 Dev 5", + "V4_STAGING": "V4 Staging", + "V4_TESTNET2": "V4 Public Testnet #2", + "V4_TESTNET2_DSRV": "V4 Public Testnet #2 DSRV", + "V4_TESTNET2_DYDX": "V4 Public Testnet #2 dYdX", + "V4_TESTNET2_NODEFLEET": "V4 Public Testnet #2 nodefleet" } } diff --git a/src/state/accountCalculators.ts b/src/state/accountCalculators.ts index 45ab47a..10f0c48 100644 --- a/src/state/accountCalculators.ts +++ b/src/state/accountCalculators.ts @@ -1,7 +1,7 @@ import { createSelector } from 'reselect'; import { SubaccountPosition } from '@/constants/abacus'; -import { OnboardingGuard, OnboardingState, OnboardingSteps } from '@/constants/account'; +import { OnboardingState, OnboardingSteps } from '@/constants/account'; import { isDydxV4Network } from '@/constants/networks'; import { diff --git a/src/views/dialogs/ExchangeOfflineDialog.tsx b/src/views/dialogs/ExchangeOfflineDialog.tsx index ead24ac..2388963 100644 --- a/src/views/dialogs/ExchangeOfflineDialog.tsx +++ b/src/views/dialogs/ExchangeOfflineDialog.tsx @@ -3,7 +3,7 @@ import styled, { AnyStyledComponent } from 'styled-components'; import { useDispatch, useSelector } from 'react-redux'; import { AbacusApiStatus } from '@/constants/abacus'; -import { DydxV4Network } from '@/constants/networks'; +import { CLIENT_NETWORK_CONFIGS } from '@/constants/networks'; import { UNICODE } from '@/constants/unicode'; import { STRING_KEYS } from '@/constants/localization'; @@ -44,7 +44,7 @@ export const ExchangeOfflineDialog = ({ preventClose, setIsOpen }: ElementProps) >

{statusErrorMessage}

- {selectedNetwork === DydxV4Network.V4Testnet2 && ( + {CLIENT_NETWORK_CONFIGS[selectedNetwork].dydxChainId === 'dydx-testnet-2' && ( {stringGetter({ key: STRING_KEYS.LEARN_MORE })} {UNICODE.ARROW_RIGHT} diff --git a/src/views/dialogs/OnboardingDialog/GenerateKeys.tsx b/src/views/dialogs/OnboardingDialog/GenerateKeys.tsx index 2a8e6b8..84a704d 100644 --- a/src/views/dialogs/OnboardingDialog/GenerateKeys.tsx +++ b/src/views/dialogs/OnboardingDialog/GenerateKeys.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import { useSignTypedData } from 'wagmi'; import styled, { type AnyStyledComponent, css } from 'styled-components'; -import { useDispatch, useSelector } from 'react-redux'; +import { useSelector } from 'react-redux'; import { AES } from 'crypto-js'; import { EvmDerivedAccountStatus } from '@/constants/account'; @@ -9,7 +9,7 @@ import { AlertType } from '@/constants/alerts'; import { AnalyticsEvent } from '@/constants/analytics'; import { ButtonAction } from '@/constants/buttons'; import { STRING_KEYS } from '@/constants/localization'; -import { CLIENT_NETWORK_CONFIGS, DydxV4Network } from '@/constants/networks'; +import { CLIENT_NETWORK_CONFIGS } from '@/constants/networks'; import { DydxAddress, SIGN_TYPED_DATA } from '@/constants/wallets'; import { useAccounts, useBreakpoints, useDydxClient, useStringGetter } from '@/hooks'; @@ -54,7 +54,7 @@ export const GenerateKeys = ({ // 1. Switch network const selectedNetwork = useSelector(getSelectedNetwork); - const chainId = Number(CLIENT_NETWORK_CONFIGS[selectedNetwork as DydxV4Network].ethereumChainId); + const chainId = Number(CLIENT_NETWORK_CONFIGS[selectedNetwork].ethereumChainId); const { isMatchingNetwork, matchNetwork, isSwitchingNetwork } = useMatchingEvmNetwork({ chainId, diff --git a/src/views/forms/DepositForm.tsx b/src/views/forms/DepositForm.tsx index d64d522..cc5e5c1 100644 --- a/src/views/forms/DepositForm.tsx +++ b/src/views/forms/DepositForm.tsx @@ -11,9 +11,9 @@ import { AlertType } from '@/constants/alerts'; import { ButtonSize } from '@/constants/buttons'; import { StringGetterFunction, STRING_KEYS } from '@/constants/localization'; import { NumberSign } from '@/constants/numbers'; -import { CLIENT_NETWORK_CONFIGS, type DydxV4Network } from '@/constants/networks'; +import { CLIENT_NETWORK_CONFIGS } from '@/constants/networks'; -import { useAccounts, useDydxClient, useStringGetter } from '@/hooks'; +import { useAccounts, useStringGetter } from '@/hooks'; import { useAccountBalance } from '@/hooks/useAccountBalance'; import { layoutMixins } from '@/styles/layoutMixins'; @@ -135,7 +135,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => { // const { networkConfig } = useDydxClient(); const selectedNetwork = useSelector(getSelectedNetwork); - const evmChainId = Number(CLIENT_NETWORK_CONFIGS[selectedNetwork as DydxV4Network].ethereumChainId); + const evmChainId = Number(CLIENT_NETWORK_CONFIGS[selectedNetwork].ethereumChainId); const { chains, tokens } = useSquidData(signerGraz ? 'cosmos' : 'evm'); diff --git a/src/views/forms/TransferForm.tsx b/src/views/forms/TransferForm.tsx index 2131411..fa1f99c 100644 --- a/src/views/forms/TransferForm.tsx +++ b/src/views/forms/TransferForm.tsx @@ -12,7 +12,7 @@ import { AlertType } from '@/constants/alerts'; import { ButtonShape, ButtonSize } from '@/constants/buttons'; import { ERROR_STRING_KEYS } from '@/constants/localization/errors'; import { STRING_KEYS } from '@/constants/localization'; -import { CHAIN_IDS } from '@/constants/networks'; +import { CLIENT_NETWORK_CONFIGS } from '@/constants/networks'; import { NumberSign, QUANTUM_MULTIPLIER } from '@/constants/numbers'; import { DYDX_CHAIN_ASSET_COIN_DENOM, DYDX_CHAIN_INFO, DydxChainAsset } from '@/constants/wallets'; @@ -228,7 +228,7 @@ export const TransferForm = ({ const networkOptions = [ { - chainId: CHAIN_IDS[selectedNetwork], + chainId: CLIENT_NETWORK_CONFIGS[selectedNetwork].dydxChainId, label: ( {stringGetter({ key: STRING_KEYS.DYDX_CHAIN })} @@ -318,7 +318,7 @@ export const TransferForm = ({ /> {networkOptions.map(({ chainId, label }) => ( diff --git a/src/views/menus/NetworkSelectMenu.tsx b/src/views/menus/NetworkSelectMenu.tsx index c95b63f..45165d7 100644 --- a/src/views/menus/NetworkSelectMenu.tsx +++ b/src/views/menus/NetworkSelectMenu.tsx @@ -1,6 +1,7 @@ import styled, { type AnyStyledComponent } from 'styled-components'; import { useSelectedNetwork } from '@/hooks'; +import { layoutMixins } from '@/styles/layoutMixins'; import { headerMixins } from '@/styles/headerMixins'; import { DropdownSelectMenu } from '@/components/DropdownSelectMenu'; @@ -18,7 +19,6 @@ export const NetworkSelectMenu = ({ align, sideOffset }: StyleProps) => { return ( = {}; Styled.DropdownSelectMenu = styled(DropdownSelectMenu)` ${headerMixins.dropdownTrigger} + + & > span:first-of-type { + ${layoutMixins.textOverflow} + max-width: 5.625rem; + min-width: 0; + white-space: nowrap; + } `; diff --git a/src/views/menus/useNetworks.tsx b/src/views/menus/useNetworks.tsx index f96e46c..0981564 100644 --- a/src/views/menus/useNetworks.tsx +++ b/src/views/menus/useNetworks.tsx @@ -1,45 +1,17 @@ -import { type MenuItem } from '@/constants/menus'; -import { type DydxNetwork, DydxV3Network, DydxV4Network } from '@/constants/networks'; +import { ENDPOINTS, DEV_ENDPOINTS } from '@dydxprotocol/v4-localization'; -export const useNetworks = (): MenuItem[] => - import.meta.env.MODE === 'production' - ? [ - { - value: DydxV4Network.V4Testnet2, - label: 'Testnet', - slotBefore: v4, - }, - ] - : [ - { - value: DydxV4Network.V4Mainnet, - label: 'Mainnet', - slotBefore: v4, - disabled: true, - }, - { - value: DydxV4Network.V4Staging, - label: 'Staging', - slotBefore: v4, - }, - { - value: DydxV4Network.V4Testnet2, - label: 'Testnet-2', - slotBefore: v4, - }, - { - value: DydxV4Network.V4Local, - label: 'Dev', - slotBefore: v4, - }, - { - value: DydxV3Network.V3Mainnet, - label: 'Mainnet', - slotBefore: v3, - }, - { - value: DydxV3Network.V3Testnet, - label: 'Testnet', - slotBefore: v3, - }, - ]; +import { type MenuItem } from '@/constants/menus'; +import { useStringGetter } from '@/hooks'; + +export const useNetworks = (): MenuItem[] => { + const stringGetter = useStringGetter(); + + const environments = + import.meta.env.MODE === 'production' ? ENDPOINTS.environments : DEV_ENDPOINTS.environments; + console.log(environments); + return environments.map(({ stringKey, environment }) => ({ + key: environment, + label: stringGetter({ key: stringKey }), + value: environment, + })); +};