diff --git a/package.json b/package.json index 3667732..26d59fc 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "bignumber.js": "^9.0.2", "copy-to-clipboard": "^3.3.1", "cosmjs-types": "^0.4.1", - "cudosjs": "^1.1.1", + "cudosjs": "^1.2.5", "detect-browser": "^5.3.0", "dompurify": "^2.3.8", "graphql": "^16.3.0", @@ -37,6 +37,7 @@ "protobufjs": "^6.11.3", "ramda": "^0.28.0", "react": "^17.0.2", + "react-currency-input-field": "^3.6.9", "react-dom": "^17.0.2", "react-google-recaptcha": "^2.1.0", "react-markdown": "^8.0.3", @@ -47,6 +48,7 @@ "redux-persist": "^6.0.0", "remark-breaks": "^3.0.2", "remark-gfm": "^3.0.1", + "svg-loaders-react": "^2.2.1", "uint8-to-base64": "^0.2.0", "vite": "^2.9.8" }, diff --git a/src/App.tsx b/src/App.tsx index 43bad6a..f55deeb 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -29,6 +29,7 @@ import { ApolloLinks, defaultApolloLinks } from 'graphql/helpers' import { CHAIN_DETAILS } from 'utils/constants' import NetworkChangingLoading from 'components/NetworkChangeLoading' import { networkLoadingStyles } from 'components/NetworkChangeLoading/styles' +import { isExtensionEnabled, SUPPORTED_WALLET } from 'cudosjs' const App = () => { const location = useLocation() @@ -46,10 +47,10 @@ const App = () => { const dispatch = useDispatch() - const connectAccount = useCallback(async (chosenNetwork: string, ledgerType: string) => { + const connectAccount = useCallback(async (chosenNetwork: string, walletName: SUPPORTED_WALLET) => { try { - const { address } = await switchLedgerType(chosenNetwork!, ledgerType) + const { address } = await switchLedgerType(chosenNetwork!, walletName) if (address !== lastLoggedAddress || lastLoggedAddress === '') { dispatch( updateUserTransactions({ @@ -61,7 +62,7 @@ const App = () => { ) } - const connectedUser = await connectUser(chosenNetwork, ledgerType) + const connectedUser = await connectUser(chosenNetwork, walletName) dispatch(updateUser(connectedUser)) } catch (e) { @@ -81,21 +82,21 @@ const App = () => { }) ) - await connectAccount(currentNetwork, CosmosNetworkConfig.KEPLR_LEDGER) + await connectAccount(currentNetwork, SUPPORTED_WALLET.Keplr) }) - if (window.cosmostation) { + if (isExtensionEnabled(SUPPORTED_WALLET.Cosmostation)) { window.cosmostation.cosmos.on('accountChanged', async () => { - await connectAccount(currentNetwork, CosmosNetworkConfig.COSMOSTATION_LEDGER) + await connectAccount(currentNetwork, SUPPORTED_WALLET.Cosmostation) }) } return () => { window.removeEventListener('keplr_keystorechange', async () => { - await connectAccount(currentNetwork, CosmosNetworkConfig.KEPLR_LEDGER) + await connectAccount(currentNetwork, SUPPORTED_WALLET.Keplr) }) window.removeEventListener('accountChanged', async () => { - await connectAccount(currentNetwork, CosmosNetworkConfig.COSMOSTATION_LEDGER) + await connectAccount(currentNetwork, SUPPORTED_WALLET.Cosmostation) }) } }, []) diff --git a/src/components/Dialog/components/DelegationModal/Delegation.tsx b/src/components/Dialog/components/DelegationModal/Delegation.tsx index 67310ca..7094072 100644 --- a/src/components/Dialog/components/DelegationModal/Delegation.tsx +++ b/src/components/Dialog/components/DelegationModal/Delegation.tsx @@ -5,7 +5,6 @@ import { InputAdornment, Button, Stack, - Tooltip } from '@mui/material' import { AccountBalanceWalletRounded as AccountBalanceWalletRoundedIcon, @@ -25,7 +24,6 @@ import { } from 'store/modal' import { calculateFee, delegate } from 'ledgers/transactions' import getMiddleEllipsis from 'utils/get_middle_ellipsis' -import CudosLogo from 'assets/vectors/cudos-logo.svg' import AvatarName from 'components/AvatarName' import { useDispatch, useSelector } from 'react-redux' import BigNumber from 'bignumber.js' @@ -38,12 +36,12 @@ import { updateUser } from 'store/profile' import { getStakedBalance, getWalletBalance } from 'utils/projectUtils' import { fetchDelegations } from 'api/getAccountDelegations' import { CHAIN_DETAILS } from 'utils/constants' - +import { customInputProps } from './helpers' import { ModalContainer, StyledTextField, SummaryContainer, - CancelRoundedIcon + CancelRoundedIcon, } from '../styles' const gasPrice = GasPrice.fromString( @@ -68,7 +66,7 @@ const Delegation: React.FC = ({ modalProps, handleModal }) => { useEffect(() => { let isMounted = true const loadBalance = async () => { - const client = await signingClient(chosenNetwork, connectedLedger) + const client = await signingClient(chosenNetwork, connectedLedger!) const walletBalance = await client.getBalance( address, @@ -106,7 +104,7 @@ const Delegation: React.FC = ({ modalProps, handleModal }) => { value: msg } - const client = await signingClient(chosenNetwork, connectedLedger) + const client = await signingClient(chosenNetwork, connectedLedger!) const gasUsed = await client.simulate(address, [msgAny], 'memo') @@ -136,12 +134,6 @@ const Delegation: React.FC = ({ modalProps, handleModal }) => { }) } - const handleAmountChange = ( - ev: React.ChangeEvent - ) => { - setDelegationAmount(ev.target.value) - } - const delayInput = _.debounce((value) => handleAmount(value), 500) const handleMaxAmount = async () => { @@ -175,7 +167,7 @@ const Delegation: React.FC = ({ modalProps, handleModal }) => { validator?.address || '', amount || '', '', - connectedLedger + connectedLedger! ) handleModal({ @@ -266,7 +258,7 @@ const Delegation: React.FC = ({ modalProps, handleModal }) => { > { CHAIN_DETAILS.CHAIN_NAME[ - chosenNetwork as keyof typeof CHAIN_DETAILS.CHAIN_NAME + chosenNetwork as keyof typeof CHAIN_DETAILS.CHAIN_NAME ] } @@ -371,44 +363,19 @@ const Delegation: React.FC = ({ modalProps, handleModal }) => { , - endAdornment: ( - - - + onPaste={(e) => e.preventDefault()} + InputProps={ + customInputProps( + delegationAmount, + setDelegationAmount, + handleMaxAmount ) - }} + } sx={(theme) => ({ background: theme.custom.backgrounds.light })} - size="small" - onChange={(e) => handleAmountChange(e)} /> diff --git a/src/components/Dialog/components/DelegationModal/helpers.tsx b/src/components/Dialog/components/DelegationModal/helpers.tsx new file mode 100644 index 0000000..02ec72c --- /dev/null +++ b/src/components/Dialog/components/DelegationModal/helpers.tsx @@ -0,0 +1,65 @@ +import { Tooltip, Button } from '@mui/material' +import CurrencyInput from 'react-currency-input-field' +import CudosLogo from 'assets/vectors/cudos-logo.svg' +import { customInputStyle } from "../styles" + +export const CustomEndAdorment = ({ + handleClick +}: { + handleClick: () => Promise +}) => { + return ( + + + + ) +} + +export const customInputProps = ( + delegationAmount: string, + setDelegationAmount: React.Dispatch>, + handleMaxAmount: () => Promise +) => { + + return { + inputComponent: + () => , + disableUnderline: true, + startAdornment: cudos-logo, + endAdornment: + } +} + +export const CustomInputComponent = ({ + displayValue, + setValue +}: { + displayValue: string, + setValue: React.Dispatch> +}) => { + + return ( + setValue(value!)} + /> + ) +} diff --git a/src/components/Dialog/components/styles.ts b/src/components/Dialog/components/styles.ts index f1213e6..b0a6ed7 100644 --- a/src/components/Dialog/components/styles.ts +++ b/src/components/Dialog/components/styles.ts @@ -1,5 +1,6 @@ import { styled, Box, TextField, BoxProps } from '@mui/material' import { CancelRounded } from '@mui/icons-material' +import { COLORS_DARK_THEME } from 'theme/colors' export const StyledTextField = styled(TextField)(({ theme }) => ({ background: theme.custom.backgrounds.dark, @@ -49,3 +50,13 @@ export const CancelRoundedIcon = styled(CancelRounded)(({ theme }) => ({ right: 32, cursor: 'pointer' })) + +export const customInputStyle = { + color: 'white', + outline: 'none', + border: '0px', + background: COLORS_DARK_THEME.LIGHT_BACKGROUND, + height: '30px', + width: '100%', + padding: '0 10px' +} diff --git a/src/components/Layout/NetworkInfo.tsx b/src/components/Layout/NetworkInfo.tsx index fe78ccc..fc9c0ae 100644 --- a/src/components/Layout/NetworkInfo.tsx +++ b/src/components/Layout/NetworkInfo.tsx @@ -58,7 +58,8 @@ const NetworkInfo = () => { setOpen(false) } - const collapsable = networksToDisplayInMenu.length > 1 + // const collapsable = networksToDisplayInMenu.length > 1 + const collapsable = false return ( diff --git a/src/components/Layout/UserInfo.tsx b/src/components/Layout/UserInfo.tsx index 3b7efeb..68cd016 100644 --- a/src/components/Layout/UserInfo.tsx +++ b/src/components/Layout/UserInfo.tsx @@ -15,6 +15,7 @@ import { CHAIN_DETAILS } from 'utils/constants' import { COLORS_DARK_THEME } from 'theme/colors' import getMiddleEllipsis from 'utils/get_middle_ellipsis' +import { SUPPORTED_WALLET } from 'cudosjs' import { styles } from './styles' const UserInfo = () => { @@ -66,7 +67,7 @@ const UserInfo = () => { Logo diff --git a/src/containers/ConnectWallet/ConnectWallet.tsx b/src/containers/ConnectWallet/ConnectWallet.tsx index 45b4746..11e1833 100644 --- a/src/containers/ConnectWallet/ConnectWallet.tsx +++ b/src/containers/ConnectWallet/ConnectWallet.tsx @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { Fragment, useEffect, useState } from 'react' -import { Box, Button, CircularProgress, Tooltip, Typography } from '@mui/material' +import { Box, Button, Tooltip, Typography } from '@mui/material' import { useNavigate } from 'react-router-dom' import { useDispatch, useSelector } from 'react-redux' import { RootState } from 'store' @@ -10,16 +10,25 @@ import InfoIcon from 'assets/vectors/info-icon.svg' import Header from 'components/Layout/Header' import { useNotifications } from 'components/NotificationPopup/hooks' import { switchLedgerType } from 'ledgers/utils' -import { COLORS_DARK_THEME } from 'theme/colors' +import { ThreeDots as ThreeDotsLoading } from 'svg-loaders-react' import LinkIcon from 'assets/vectors/link-icon.svg?component' +import { + detectUserBrowser, + getExtensionUrlForBrowser, + getSupportedBrowsersForWallet, + getSupportedWallets, + isExtensionAvailableForBrowser, + isExtensionEnabled, + isSupportedBrowser, + SUPPORTED_BROWSER, + SUPPORTED_WALLET +} from 'cudosjs' + import { connectUser, delay, - getUserBrowserType, - SUPPORTED_BROWSERS, - SUPPORTED_LEDGERS, - WALLET_EXTENSIONS_URL + SUPPORTED_WALLET_LOGOS } from 'utils/projectUtils' import { styles } from './styles' @@ -30,36 +39,32 @@ const ConnectWallet = () => { const { lastLoggedAddress, chosenNetwork: currentNetwork } = useSelector((state: RootState) => state.profile) const { setWarning } = useNotifications() const [loading, setLoading] = useState(new Map()) - const [availableLedgers, setAvailableLedgers] = useState>({}) - const [userBrowser, setUserBrowser] = useState(undefined) - - const redirectToExtension = (ledgerType: string, browserType: SUPPORTED_BROWSERS | undefined) => { - - let url = WALLET_EXTENSIONS_URL[ledgerType][browserType!] || '' + const [userBrowser, setUserBrowser] = useState(undefined) - if (url) { - window.open(url, '_blank')?.focus() + const redirectToExtension = (extensionUrl: string | undefined) => { + if (extensionUrl) { + window.open(extensionUrl, '_blank')?.focus() } } - const connect = async (chosenNetwork: string, ledgerType: string) => { + const connect = async (chosenNetwork: string, walletName: SUPPORTED_WALLET) => { try { - setLoading(new Map(loading.set(ledgerType, true))) + setLoading(new Map(loading.set(walletName, true))) await delay(1000) - const { address } = await switchLedgerType(chosenNetwork, ledgerType) + const { address } = await switchLedgerType(chosenNetwork, walletName) if (address !== lastLoggedAddress) { dispatch(updateUserTransactions({ offsetCount: 0, data: [] })) } - const connectedUser = await connectUser(chosenNetwork, ledgerType) + const connectedUser = await connectUser(chosenNetwork, walletName) dispatch(updateUser(connectedUser)) navigate('dashboard') } catch (error) { setWarning( - `Failed connecting to wallet! Please check your ${ledgerType} installation.` + `Failed connecting to wallet! Please check your ${walletName} installation.` ) } finally { @@ -67,44 +72,31 @@ const ConnectWallet = () => { } } - const click = (ledgerType: string) => { + const click = (walletName: SUPPORTED_WALLET) => { - if (availableLedgers[ledgerType]) { - connect(currentNetwork, ledgerType) + if (isExtensionEnabled(walletName)) { + connect(currentNetwork, walletName) return } - redirectToExtension(ledgerType, userBrowser) + const extensionUrl = getExtensionUrlForBrowser(walletName, userBrowser!) + redirectToExtension(extensionUrl) } - const btnText = (ledgerType: string): string | JSX.Element => { + const btnText = (walletName: SUPPORTED_WALLET): string | JSX.Element => { - if (loading.get(ledgerType)) { - return ( - - - Loading... - - - - ) + if (loading.get(walletName)) { + return } - if (availableLedgers[ledgerType]) { - return `Connect ${ledgerType} wallet` + if (isExtensionEnabled(walletName)) { + return `Connect ${walletName} wallet` } - if (WALLET_EXTENSIONS_URL[ledgerType][userBrowser!]) { + if (isExtensionAvailableForBrowser(walletName, userBrowser!)) { return ( - {`Get ${ledgerType} plugin`} + {`Get ${walletName} plugin`} ) @@ -113,55 +105,63 @@ const ConnectWallet = () => { return 'Unsupported browser' } - const btnTooltip = (ledgerType: string): string => { + const btnTooltip = (walletName: SUPPORTED_WALLET): string => { let tooltipText = '' - if (!WALLET_EXTENSIONS_URL[ledgerType][userBrowser!]) { - tooltipText = `${ledgerType} supports: ${Object.entries( - WALLET_EXTENSIONS_URL[ledgerType]).map(([key]) => { - return ` ${key}` - })}` + // We only need a tooltip for a wallet not supported by the current browser + if (!isExtensionAvailableForBrowser(walletName, userBrowser!)) { + tooltipText = `${walletName} supports: ${getSupportedBrowsersForWallet(walletName).map((browser) => { + return ` ${browser}` + })}` } return tooltipText } - const isDisabledBtn = (ledgerType: string): boolean => { + const isDisabledBtn = (walletName: SUPPORTED_WALLET): boolean => { - // Disabling the Btn if cicked into loading state - if (loading.get(ledgerType)) { + // Disabling the Btn if into loading state + if (loading.get(walletName)) { return true } - // Disabling the btn, when other btnType is loading + // Disabling the btn, when other btn is loading if (loading.size > 0) { return true } // Disabling the btn if no extension is available for the current user browser - if (!WALLET_EXTENSIONS_URL[ledgerType][userBrowser!]) { + if (!isExtensionAvailableForBrowser(walletName, userBrowser!)) { return true } return false } - useEffect(() => { - - const userLedgers: Record = {} - - for (const ledger of SUPPORTED_LEDGERS) { - userLedgers[ledger.type] = ledger.isInstalled() + const displayLogo = (walletName: SUPPORTED_WALLET): JSX.Element => { + if (loading.get(walletName)) { + return } - setAvailableLedgers(userLedgers) + return SUPPORTED_WALLET_LOGOS[walletName] || + } - }, [loading]) + const LoadingButtonComponent = (): JSX.Element => { + return ( + + ) + } useEffect(() => { - - setUserBrowser(getUserBrowserType()) + const userBrowser = detectUserBrowser() + if (isSupportedBrowser(userBrowser)) { + setUserBrowser(userBrowser as SUPPORTED_BROWSER) + return + } + setUserBrowser(undefined) }, []) return ( @@ -178,19 +178,19 @@ const ConnectWallet = () => { order to continue you need to connect your Keplr Wallet. - {SUPPORTED_LEDGERS.map((ledger) => { + {getSupportedWallets().map((wallet) => { return ( - + diff --git a/src/containers/Dashboard/WalletInformation/components/ClaimRewardsModal/Rewards.tsx b/src/containers/Dashboard/WalletInformation/components/ClaimRewardsModal/Rewards.tsx index badca42..72f8879 100644 --- a/src/containers/Dashboard/WalletInformation/components/ClaimRewardsModal/Rewards.tsx +++ b/src/containers/Dashboard/WalletInformation/components/ClaimRewardsModal/Rewards.tsx @@ -90,7 +90,7 @@ const Rewards: React.FC = ({ modalProps, handleModal }) => { withdrawCommission: isValidator, claimAndRestakeSeparateMsg }, - connectedLedger + connectedLedger! ) handleModal({ diff --git a/src/containers/Proposals/components/DepositModal/Deposit.tsx b/src/containers/Proposals/components/DepositModal/Deposit.tsx index 4cfb236..2f105d4 100644 --- a/src/containers/Proposals/components/DepositModal/Deposit.tsx +++ b/src/containers/Proposals/components/DepositModal/Deposit.tsx @@ -51,7 +51,7 @@ const Deposit: React.FC = ({ handleModal, modalProps }) => { depositorAddress, proposalId, amount, - connectedLedger + connectedLedger! ) handleModal({ diff --git a/src/containers/Proposals/components/ProposalModal/Proposals.tsx b/src/containers/Proposals/components/ProposalModal/Proposals.tsx index d50d86b..69c8835 100644 --- a/src/containers/Proposals/components/ProposalModal/Proposals.tsx +++ b/src/containers/Proposals/components/ProposalModal/Proposals.tsx @@ -99,7 +99,7 @@ const Proposals: React.FC = ({ handleModal, modalProps }) => { chosenNetwork, proposalData, proposerAddress, - connectedLedger + connectedLedger! ) handleModal({ open: true, diff --git a/src/containers/Proposals/components/VotingModal/Vote.tsx b/src/containers/Proposals/components/VotingModal/Vote.tsx index ff73c81..ea84e06 100644 --- a/src/containers/Proposals/components/VotingModal/Vote.tsx +++ b/src/containers/Proposals/components/VotingModal/Vote.tsx @@ -42,7 +42,7 @@ const Vote: React.FC = ({ handleModal, modalProps }) => { voterAddress, proposalId, votingOption, - connectedLedger + connectedLedger! ) handleModal({ diff --git a/src/containers/ValidatorDetails/components/Details/components/ValidatorInfo/components/RedelegationModal/Redelegation.tsx b/src/containers/ValidatorDetails/components/Details/components/ValidatorInfo/components/RedelegationModal/Redelegation.tsx index fbe97c9..d33ca3c 100644 --- a/src/containers/ValidatorDetails/components/Details/components/ValidatorInfo/components/RedelegationModal/Redelegation.tsx +++ b/src/containers/ValidatorDetails/components/Details/components/ValidatorInfo/components/RedelegationModal/Redelegation.tsx @@ -87,7 +87,7 @@ const Redelegation: React.FC = ({ useEffect(() => { const loadBalance = async () => { - const client = await signingClient(chosenNetwork, connectedLedger) + const client = await signingClient(chosenNetwork, connectedLedger!) const walletBalance = await client.getDelegation( address, @@ -128,7 +128,7 @@ const Redelegation: React.FC = ({ value: msg } - const client = await signingClient(chosenNetwork, connectedLedger) + const client = await signingClient(chosenNetwork, connectedLedger!) const gasUsed = await client.simulate(address, [msgAny], 'memo') @@ -174,7 +174,7 @@ const Redelegation: React.FC = ({ value: msg } - const client = await signingClient(chosenNetwork, connectedLedger) + const client = await signingClient(chosenNetwork, connectedLedger!) const gasUsed = await client.simulate(address, [msgAny], 'memo') @@ -227,7 +227,7 @@ const Redelegation: React.FC = ({ redelegationAddress, amount || '', '', - connectedLedger + connectedLedger! ) handleModal({ diff --git a/src/containers/ValidatorDetails/components/Details/components/ValidatorInfo/components/UndelegationModal/Undelegation.tsx b/src/containers/ValidatorDetails/components/Details/components/ValidatorInfo/components/UndelegationModal/Undelegation.tsx index 2af4471..ef4af84 100644 --- a/src/containers/ValidatorDetails/components/Details/components/ValidatorInfo/components/UndelegationModal/Undelegation.tsx +++ b/src/containers/ValidatorDetails/components/Details/components/ValidatorInfo/components/UndelegationModal/Undelegation.tsx @@ -56,7 +56,7 @@ const Undelegation: React.FC = ({ useEffect(() => { const loadBalance = async () => { - const client = await signingClient(chosenNetwork, connectedLedger) + const client = await signingClient(chosenNetwork, connectedLedger!) const walletBalance = await client.getDelegation( address, @@ -91,7 +91,7 @@ const Undelegation: React.FC = ({ value: msg } - const client = await signingClient(chosenNetwork, connectedLedger) + const client = await signingClient(chosenNetwork, connectedLedger!) const gasUsed = await client.simulate(address, [msgAny], 'memo') @@ -136,7 +136,7 @@ const Undelegation: React.FC = ({ value: msg } - const client = await signingClient(chosenNetwork, connectedLedger) + const client = await signingClient(chosenNetwork, connectedLedger!) const gasUsed = await client.simulate(address, [msgAny], 'memo') @@ -177,7 +177,7 @@ const Undelegation: React.FC = ({ validator?.address || '', amount || '', '', - connectedLedger + connectedLedger! ) handleModal({ diff --git a/src/ledgers/transactions.ts b/src/ledgers/transactions.ts index 11af996..15d68e2 100644 --- a/src/ledgers/transactions.ts +++ b/src/ledgers/transactions.ts @@ -31,7 +31,8 @@ import { MsgDepositEncodeObject, MsgSubmitProposalEncodeObject, MsgUndelegateEncodeObject, - DEFAULT_GAS_MULTIPLIER + DEFAULT_GAS_MULTIPLIER, + SUPPORTED_WALLET } from 'cudosjs' import { encode } from 'uint8-to-base64' import Long from 'long' @@ -72,7 +73,7 @@ export const calculateFee = (gasLimit: number, gasPrice: string | GasPrice) => { export const getFee = async ( chosenNetwork: string, address: string, - ledgerType: string, + ledgerType: SUPPORTED_WALLET, message: any[], memo: string ) => { @@ -92,7 +93,7 @@ export const delegate = async ( validatorAddress: string, amount: string, memo: string, - ledgerType: string + ledgerType: SUPPORTED_WALLET ): Promise => { const delegationAmount = { amount: new BigNumber(amount) @@ -138,7 +139,7 @@ export const undelegate = async ( validatorAddress: string, amount: string, memo: string, - ledgerType: string + ledgerType: SUPPORTED_WALLET ): Promise => { const undelegationAmount = { amount: new BigNumber(amount || 0) @@ -185,7 +186,7 @@ export const redelegate = async ( validatorDstAddress: string, amount: string, memo: string, - ledgerType: string + ledgerType: SUPPORTED_WALLET ): Promise => { const msg = MsgBeginRedelegate.fromPartial({ delegatorAddress, @@ -227,7 +228,7 @@ export const claimRewards = async ( withdrawCommission: boolean claimAndRestakeSeparateMsg: boolean }, - ledgerType: string + ledgerType: SUPPORTED_WALLET ) => { const { restake, withdrawCommission, claimAndRestakeSeparateMsg } = options const msgMemo = '' @@ -332,7 +333,7 @@ export const voteProposal = async ( voterAddress: string, proposalId: number | undefined, votingOption: number, - ledgerType: string + ledgerType: SUPPORTED_WALLET ) => { const msg = MsgVote.fromPartial({ proposalId, @@ -369,7 +370,7 @@ export const depositProposal = async ( depositorAddress: string, proposalId: number | undefined, amount: string, - ledgerType: string + ledgerType: SUPPORTED_WALLET ) => { const msg = MsgDeposit.fromPartial({ proposalId, @@ -508,7 +509,7 @@ export const createProposal = async ( chosenNetwork: string, proposalData: any, proposerAddress: string, - ledgerType: string + ledgerType: SUPPORTED_WALLET ) => { const client = await signingClient(chosenNetwork, ledgerType) diff --git a/src/ledgers/utils.ts b/src/ledgers/utils.ts index 354cb77..66217a9 100644 --- a/src/ledgers/utils.ts +++ b/src/ledgers/utils.ts @@ -1,8 +1,10 @@ import { + isExtensionEnabled, OfflineAminoSigner, OfflineSigner, SigningStargateClient, - StargateClient + StargateClient, + SUPPORTED_WALLET } from 'cudosjs' import { getOfflineSigner as cosmostationSigner } from '@cosmostation/cosmos-client' import { @@ -10,11 +12,9 @@ import { SignAminoDoc } from '@cosmostation/extension-client/types/message' import { cosmos, Cosmos } from '@cosmostation/extension-client' -import CosmosNetworkConfig from './CosmosNetworkConfig' import { connectKeplrLedger } from './KeplrLedger' import { connectCosmostationLedger } from './CosmoStationLedger' import { CHAIN_DETAILS } from 'utils/constants' -import { isCosmostationInstalled, isKeplrInstalled } from 'utils/projectUtils' const colors = { staking: '#3d5afe', @@ -449,13 +449,15 @@ export const unknownMessage = { displayName: 'Unknown' } -export const switchLedgerType = async (chosenNetwork: string, ledgerType: string) => { +export const switchLedgerType = async (chosenNetwork: string, walletName: SUPPORTED_WALLET) => { - if (ledgerType === CosmosNetworkConfig.KEPLR_LEDGER && isKeplrInstalled()) { + const isInstalled = isExtensionEnabled(walletName) + + if (walletName === SUPPORTED_WALLET.Keplr && isInstalled) { return connectKeplrLedger(chosenNetwork) } - if (ledgerType === CosmosNetworkConfig.COSMOSTATION_LEDGER && isCosmostationInstalled()) { + if (walletName === SUPPORTED_WALLET.Cosmostation && isInstalled) { return connectCosmostationLedger(chosenNetwork) } @@ -498,16 +500,16 @@ export const getLedgerSigner = async ( const switchSigningClient = async ( chosenNetwork: string, - ledgerType: string + walletName: SUPPORTED_WALLET ): Promise => { let client - switch (ledgerType) { - case CosmosNetworkConfig.KEPLR_LEDGER: + switch (walletName) { + case SUPPORTED_WALLET.Keplr: client = await window.getOfflineSignerAuto( CHAIN_DETAILS.CHAIN_ID[chosenNetwork as keyof typeof CHAIN_DETAILS.CHAIN_ID] ) return client - case CosmosNetworkConfig.COSMOSTATION_LEDGER: { + case SUPPORTED_WALLET.Cosmostation: { const connector = await cosmos() const connectedAccount = await connector.requestAccount( @@ -528,10 +530,10 @@ const switchSigningClient = async ( } } -export const signingClient = async (chosenNetwork: string, ledgerType: string) => { - const offlineSigner = await switchSigningClient(chosenNetwork, ledgerType) +export const signingClient = async (chosenNetwork: string, walletName: SUPPORTED_WALLET) => { + const offlineSigner = await switchSigningClient(chosenNetwork, walletName) - if (window.keplr) { + if (isExtensionEnabled(walletName)) { window.keplr.defaultOptions = { sign: { preferNoSetFee: true diff --git a/src/store/profile.ts b/src/store/profile.ts index 1cf4da5..eb51717 100644 --- a/src/store/profile.ts +++ b/src/store/profile.ts @@ -1,5 +1,6 @@ -import { createSlice, PayloadAction } from '@reduxjs/toolkit' +import { createSlice } from '@reduxjs/toolkit' import BigNumber from 'bignumber.js' +import { SUPPORTED_WALLET } from 'cudosjs' import { CHAIN_DETAILS } from 'utils/constants' export enum TooltipMessages { @@ -12,7 +13,7 @@ export enum TooltipMessages { export interface WalletState { address: string accountName: string - connectedLedger: string + connectedLedger: SUPPORTED_WALLET | undefined chosenNetwork: string loadingState: boolean lastLoggedAddress: string @@ -37,7 +38,7 @@ export interface WalletState { const initialState: WalletState = { address: '', accountName: '', - connectedLedger: '', + connectedLedger: undefined, chosenNetwork: CHAIN_DETAILS.DEFAULT_NETWORK, loadingState: false, lastLoggedAddress: '', diff --git a/src/utils/projectUtils.tsx b/src/utils/projectUtils.tsx index b5813d4..d2eb43d 100644 --- a/src/utils/projectUtils.tsx +++ b/src/utils/projectUtils.tsx @@ -14,6 +14,7 @@ import { detect as detectBrowser } from 'detect-browser' import CosmostationLogo from 'assets/vectors/cosmostation-logo.svg' import KeplrLogo from 'assets/vectors/keplr-logo.svg' import { styles } from 'containers/ConnectWallet/styles' +import { SUPPORTED_WALLET } from 'cudosjs' export const isValidCudosAddress = (address: string) => { if (address === '' || address === undefined) { @@ -93,11 +94,11 @@ export const addEndingEllipsis = ( return input } -export const connectUser = async (chosenNetwork: string, ledgerType: string): Promise => { +export const connectUser = async (chosenNetwork: string, walletName: SUPPORTED_WALLET): Promise => { try { - const { address, accountName } = await switchLedgerType(chosenNetwork!, ledgerType) + const { address, accountName } = await switchLedgerType(chosenNetwork!, walletName) const balance = await getWalletBalance(chosenNetwork, address!) const stakedAmountBalance = await getStakedBalance(chosenNetwork, address!) const { totalRewards, validatorArray } = await fetchRewards(chosenNetwork, address!) @@ -110,7 +111,7 @@ export const connectUser = async (chosenNetwork: string, ledgerType: string): Pr chosenNetwork, address, lastLoggedAddress: address, - connectedLedger: ledgerType, + connectedLedger: walletName, accountName, balance: new BigNumber(balance), availableRewards: new BigNumber(totalRewards), @@ -149,63 +150,11 @@ export const handleAvailableNetworks = (defaultNetwork: string): networkToDispla return [CHAIN_DETAILS.PUBLIC, CHAIN_DETAILS.MAINNET] } -export const isKeplrInstalled = () => { - return window.keplr?.enable.length > 0 -} - -export const isCosmostationInstalled = () => { - if (window.cosmostation) { - return true - } - - return false -} - export const delay = (ms: number) => { return new Promise(resolve => setTimeout(resolve, ms)) } -export const SUPPORTED_LEDGERS = [ - { - type: CosmosNetworkConfig.KEPLR_LEDGER, - logo: Keplr Logo, - isInstalled: isKeplrInstalled - }, - { - type: CosmosNetworkConfig.COSMOSTATION_LEDGER, - logo: Cosmostation Logo, - isInstalled: isCosmostationInstalled - } -] - -export enum SUPPORTED_BROWSERS { - chrome = 'chrome', - firefox = 'firefox', - edge = 'edge' -} - -export const WALLET_EXTENSIONS_URL = { - [CosmosNetworkConfig.KEPLR_LEDGER]: { - [SUPPORTED_BROWSERS.chrome]: 'https://chrome.google.com/webstore/detail/keplr/dmkamcknogkgcdfhhbddcghachkejeap?hl=en', - [SUPPORTED_BROWSERS.firefox]: 'https://addons.mozilla.org/en-US/firefox/addon/keplr/', - [SUPPORTED_BROWSERS.edge]: 'https://microsoftedge.microsoft.com/addons/detail/keplr/efknohjclbjfppcmniflbmnokbihoofp?hl=en-GB' - }, - [CosmosNetworkConfig.COSMOSTATION_LEDGER]: { - [SUPPORTED_BROWSERS.chrome]: 'https://chrome.google.com/webstore/detail/cosmostation/fpkhgmpbidmiogeglndfbkegfdlnajnf?utm_source=chrome-ntp-icon' - } -} - -export const getUserBrowserType = (): SUPPORTED_BROWSERS | undefined => { - - let detectedBrowser = detectBrowser()?.name - - if (detectedBrowser === 'edge-chromium') { - detectedBrowser = 'edge' - } - - if (SUPPORTED_BROWSERS[detectedBrowser as SUPPORTED_BROWSERS]) { - return detectedBrowser as SUPPORTED_BROWSERS - } - - return undefined +export const SUPPORTED_WALLET_LOGOS = { + [SUPPORTED_WALLET.Keplr]: Keplr Logo, + [SUPPORTED_WALLET.Cosmostation]: Cosmostation Logo } diff --git a/types/svg-loaders-react/index.d.ts b/types/svg-loaders-react/index.d.ts new file mode 100644 index 0000000..2a33e17 --- /dev/null +++ b/types/svg-loaders-react/index.d.ts @@ -0,0 +1 @@ +declare module 'svg-loaders-react' \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index dbe9e45..b11e242 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1012,6 +1012,11 @@ resolved "https://registry.yarnpkg.com/@cosmostation/extension-client/-/extension-client-0.1.11.tgz#d6b447cfd9cf7613ec485b57327819b14735cf13" integrity sha512-CkmNPmYn07UhP0z3PxGRRpgTcBJ/gS1ay/J2jfYsBi/4gnXvpQ3xOZdMU0qdxhFOjh1Xt7kflYsztk9ljMnJcw== +"@cosmostation/extension-client@^0.1.9": + version "0.1.15" + resolved "https://registry.yarnpkg.com/@cosmostation/extension-client/-/extension-client-0.1.15.tgz#cdc6d8fce42217704c1c0d5814f0ee7ce27e8dab" + integrity sha512-HlXYJjFrNpjiV/GUKhri1UL8/bhlOIFFLpRF78YDSqq16x0+plIqx5CAvEusFcKTDpVfpeD5sfUHiKvP7euNFg== + "@cosmostation/wc-modal@^0.0.4": version "0.0.4" resolved "https://registry.yarnpkg.com/@cosmostation/wc-modal/-/wc-modal-0.0.4.tgz#61442b0c51201dda9ee90cfcb3002848eadc7ba2" @@ -3257,17 +3262,20 @@ csstype@^3.0.11, csstype@^3.0.2: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33" integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw== -cudosjs@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/cudosjs/-/cudosjs-1.1.1.tgz#2e9bfcf910c37559d2a4d86976f9d418794d2383" - integrity sha512-IPIO0+9jQ3ovl/6LGI/NwKP2r3yl36R7evDSaeiQj1hxfDdY3M0IcTbxYAqOhkptmdsqpPVre/MZAqVR00mAUA== +cudosjs@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/cudosjs/-/cudosjs-1.2.5.tgz#b491316aea38399ea7800c0b4bc3d615481fd7e7" + integrity sha512-LignXN62Ni355FlU+5A8liwoktKkXffV2rHpCKmrRKPljIPEyrRrtjs0YOHFDbbioouqmZXlQb+z2mgfErPknw== dependencies: "@cosmjs/cosmwasm-stargate" "^0.28.4" "@cosmjs/crypto" "^0.28.4" "@cosmjs/proto-signing" "^0.28.4" "@cosmjs/stargate" "^0.28.4" "@cosmjs/tendermint-rpc" "^0.28.4" + "@cosmostation/cosmos-client" "^0.0.4" + "@cosmostation/extension-client" "^0.1.9" bignumber.js "^9.0.2" + detect-browser "^5.3.0" yarn "^1.22.19" damerau-levenshtein@^1.0.7: @@ -6493,6 +6501,11 @@ react-async-script@^1.1.1: hoist-non-react-statics "^3.3.0" prop-types "^15.5.0" +react-currency-input-field@^3.6.9: + version "3.6.9" + resolved "https://registry.yarnpkg.com/react-currency-input-field/-/react-currency-input-field-3.6.9.tgz#5eaa1190512d1de214863032045b67dd0582c87a" + integrity sha512-GNqG1Np+dz3VfBhDc9pFPIyar9SgB/fRjIofFSXOoyFNffda5r24n6LSoXfqQ9L7IKRDoUwveMMJV5GCM2eByw== + react-dom@^16.14.0: version "16.14.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89" @@ -7289,6 +7302,11 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +svg-loaders-react@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/svg-loaders-react/-/svg-loaders-react-2.2.1.tgz#d546cea2a895144cfd652e1bd846166d8a07d2ed" + integrity sha512-ATfg5pAMOla2GqPcwGRDrNTLlTQzl2fMvfW290j20qH7qpB61C3SQAnu+T9t8Z+V4IKKN2Bm1d/SaCv5IR1DDA== + svg-parser@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5"