fix: fixed the wallet auto connection (#341)
* fix: fixed the wallet auto connection * tidy: refactor * fix: re-enabled account change support * tidy: refactor
This commit is contained in:
parent
267b968c4a
commit
cec9e50955
@ -2,8 +2,8 @@ import { useShuttle } from '@delphi-labs/shuttle-react'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import classNames from 'classnames'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import useClipboard from 'react-use-clipboard'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
import useClipboard from 'react-use-clipboard'
|
||||
|
||||
import Button from 'components/Button'
|
||||
import { CircularProgress } from 'components/CircularProgress'
|
||||
@ -60,7 +60,7 @@ export default function WalletConnectedButton() {
|
||||
const onDisconnectWallet = () => {
|
||||
if (!currentWallet) return
|
||||
disconnectWallet(currentWallet)
|
||||
useStore.setState({ client: undefined, balances: [] })
|
||||
useStore.setState({ client: undefined, address: undefined, accounts: null, balances: [] })
|
||||
navigate(getRoute(getPage(pathname)))
|
||||
}
|
||||
|
||||
|
94
src/components/Wallet/WalletConnecting.tsx
Normal file
94
src/components/Wallet/WalletConnecting.tsx
Normal file
@ -0,0 +1,94 @@
|
||||
import { CosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import { useShuttle } from '@delphi-labs/shuttle-react'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
import { CircularProgress } from 'components/CircularProgress'
|
||||
import FullOverlayContent from 'components/FullOverlayContent'
|
||||
import WalletSelect from 'components/Wallet//WalletSelect'
|
||||
import WalletFetchBalancesAndAccounts from 'components/Wallet/WalletFetchBalancesAndAccounts'
|
||||
import { CHAINS } from 'constants/chains'
|
||||
import { ENV } from 'constants/env'
|
||||
import useToggle from 'hooks/useToggle'
|
||||
import useStore from 'store'
|
||||
|
||||
interface Props {
|
||||
autoConnect?: boolean
|
||||
providerId?: string
|
||||
}
|
||||
|
||||
const currentChainId = ENV.CHAIN_ID
|
||||
const currentChain = CHAINS[currentChainId]
|
||||
|
||||
const mapErrorMessages = (providerId: string, errorMessage: string) => {
|
||||
if (providerId === 'station') {
|
||||
if (errorMessage.match('Wallet not connected to the network with chainId')) {
|
||||
return `Your wallet is not connected to the correct network. Please switch your wallet to the ${currentChain.name} network`
|
||||
}
|
||||
}
|
||||
|
||||
return errorMessage
|
||||
}
|
||||
|
||||
export default function WalletConnecting(props: Props) {
|
||||
const { extensionProviders, recentWallet, connect, simulate, sign, broadcast } = useShuttle()
|
||||
const [isConnecting, setIsConnecting] = useToggle()
|
||||
const providerId = props.providerId ?? recentWallet?.providerId
|
||||
const isAutoConnect = props.autoConnect
|
||||
|
||||
const handleConnect = async (extensionProviderId: string) => {
|
||||
setIsConnecting(true)
|
||||
|
||||
try {
|
||||
const provider = extensionProviders.find((p) => p.id === providerId)
|
||||
const response =
|
||||
isAutoConnect && provider
|
||||
? await provider.connect({ chainId: currentChainId })
|
||||
: await connect({ extensionProviderId, chainId: currentChainId })
|
||||
const cosmClient = await CosmWasmClient.connect(response.network.rpc)
|
||||
const walletClient: WalletClient = {
|
||||
broadcast,
|
||||
cosmWasmClient: cosmClient,
|
||||
connectedWallet: response,
|
||||
sign,
|
||||
simulate,
|
||||
}
|
||||
setIsConnecting(false)
|
||||
useStore.setState({
|
||||
client: walletClient,
|
||||
address: response.account.address,
|
||||
focusComponent: <WalletFetchBalancesAndAccounts />,
|
||||
})
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
setIsConnecting(false)
|
||||
useStore.setState({
|
||||
client: undefined,
|
||||
address: undefined,
|
||||
accounts: null,
|
||||
focusComponent: (
|
||||
<WalletSelect
|
||||
error={{
|
||||
title: 'Failed to connect to wallet',
|
||||
message: mapErrorMessages(extensionProviderId, error.message),
|
||||
}}
|
||||
/>
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isConnecting || !providerId) return
|
||||
handleConnect(providerId)
|
||||
}, [isConnecting, providerId, handleConnect])
|
||||
|
||||
return (
|
||||
<FullOverlayContent
|
||||
title={'Connecting...'}
|
||||
copy={'Unlock your wallet and approve the connection'}
|
||||
>
|
||||
<CircularProgress size={40} />
|
||||
</FullOverlayContent>
|
||||
)
|
||||
}
|
@ -1,23 +1,29 @@
|
||||
import { CosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import { useShuttle } from '@delphi-labs/shuttle-react'
|
||||
import Image from 'next/image'
|
||||
import React, { useState } from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import QRCode from 'react-qr-code'
|
||||
|
||||
import Button from 'components/Button'
|
||||
import { CircularProgress } from 'components/CircularProgress'
|
||||
import FullOverlayContent from 'components/FullOverlayContent'
|
||||
import { ChevronLeft, ChevronRight } from 'components/Icons'
|
||||
import Text from 'components/Text'
|
||||
import WalletFetchBalancesAndAccounts from 'components/Wallet/WalletFetchBalancesAndAccounts'
|
||||
import WalletConnecting from 'components/Wallet/WalletConnecting'
|
||||
import { CHAINS } from 'constants/chains'
|
||||
import { ENV } from 'constants/env'
|
||||
import { WALLETS } from 'constants/wallets'
|
||||
import useToggle from 'hooks/useToggle'
|
||||
import useStore from 'store'
|
||||
import { WalletID } from 'types/enums/wallet'
|
||||
import { isAndroid, isIOS, isMobile } from 'utils/mobile'
|
||||
|
||||
interface Props {
|
||||
error?: ErrorObject
|
||||
}
|
||||
|
||||
interface ErrorObject {
|
||||
title: string
|
||||
message: string
|
||||
}
|
||||
|
||||
interface WalletOptionProps {
|
||||
name: string
|
||||
imageSrc: string
|
||||
@ -27,16 +33,6 @@ interface WalletOptionProps {
|
||||
const currentChainId = ENV.CHAIN_ID
|
||||
const currentChain = CHAINS[currentChainId]
|
||||
|
||||
const mapErrorMessages = (providerId: string, errorMessage: string) => {
|
||||
if (providerId === 'station') {
|
||||
if (errorMessage.match('Wallet not connected to the network with chainId')) {
|
||||
return `Your wallet is not connected to the correct network. Please switch your wallet to the ${currentChain.name} network`
|
||||
}
|
||||
}
|
||||
|
||||
return errorMessage
|
||||
}
|
||||
|
||||
function WalletOption(props: WalletOptionProps) {
|
||||
return (
|
||||
<Button
|
||||
@ -57,44 +53,16 @@ function WalletOption(props: WalletOptionProps) {
|
||||
)
|
||||
}
|
||||
|
||||
export default function WalletSelect() {
|
||||
const { extensionProviders, mobileProviders, connect, mobileConnect, simulate, sign, broadcast } =
|
||||
useShuttle()
|
||||
const [isConnecting, setIsConnecting] = useToggle(false)
|
||||
export default function WalletSelect(props: Props) {
|
||||
const { extensionProviders, mobileProviders, mobileConnect } = useShuttle()
|
||||
const [qrCodeUrl, setQRCodeUrl] = useState('')
|
||||
|
||||
const [error, setError] = useState(props.error)
|
||||
const sortedExtensionProviders = extensionProviders.sort((a, b) => +b - +a)
|
||||
|
||||
const handleConnectClick = async (extensionProviderId: string, chainId: string) => {
|
||||
setIsConnecting(true)
|
||||
|
||||
try {
|
||||
const response = await connect({ extensionProviderId, chainId })
|
||||
const cosmClient = await CosmWasmClient.connect(response.network.rpc)
|
||||
const walletClient: WalletClient = {
|
||||
broadcast,
|
||||
cosmWasmClient: cosmClient,
|
||||
connectedWallet: response,
|
||||
sign,
|
||||
simulate,
|
||||
}
|
||||
useStore.setState({
|
||||
client: walletClient,
|
||||
address: response.account.address,
|
||||
focusComponent: <WalletFetchBalancesAndAccounts />,
|
||||
})
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
useStore.setState({
|
||||
toast: {
|
||||
isError: true,
|
||||
title: 'Failed to connect to wallet',
|
||||
message: mapErrorMessages(extensionProviderId, error.message),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
setIsConnecting(false)
|
||||
const handleConnectClick = (extensionProviderId: string) => {
|
||||
useStore.setState({
|
||||
focusComponent: <WalletConnecting providerId={extensionProviderId} />,
|
||||
})
|
||||
}
|
||||
|
||||
const handleMobileConnectClick = async (mobileProviderId: string, chainId: string) => {
|
||||
@ -112,33 +80,27 @@ export default function WalletSelect() {
|
||||
} else {
|
||||
window.location.href = urls.androidUrl
|
||||
}
|
||||
setIsConnecting(true)
|
||||
} else {
|
||||
setQRCodeUrl(urls.qrCodeUrl)
|
||||
setIsConnecting(false)
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
useStore.setState({
|
||||
toast: {
|
||||
isError: true,
|
||||
title: 'Failed to connect to wallet',
|
||||
message: error.message,
|
||||
},
|
||||
})
|
||||
setError({ title: 'Failed to connect to wallet', message: error.message })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isConnecting)
|
||||
return (
|
||||
<FullOverlayContent
|
||||
title={'Connecting...'}
|
||||
copy={'Unlock your wallet and approve the connection'}
|
||||
>
|
||||
<CircularProgress size={40} />
|
||||
</FullOverlayContent>
|
||||
)
|
||||
useEffect(() => {
|
||||
if (error?.message && error?.title) {
|
||||
useStore.setState({
|
||||
toast: {
|
||||
isError: true,
|
||||
title: error.title,
|
||||
message: error.message,
|
||||
},
|
||||
})
|
||||
}
|
||||
}, [error?.message, error?.title])
|
||||
|
||||
if (qrCodeUrl)
|
||||
return (
|
||||
@ -193,7 +155,7 @@ export default function WalletSelect() {
|
||||
return (
|
||||
<WalletOption
|
||||
key={`${walletId}-${network.chainId}`}
|
||||
handleClick={() => handleConnectClick(walletId, network.chainId)}
|
||||
handleClick={() => handleConnectClick(walletId)}
|
||||
imageSrc={WALLETS[walletId].imageURL}
|
||||
name={WALLETS[walletId].name ?? 'Conenct Wallet'}
|
||||
/>
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { CosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import { useShuttle } from '@delphi-labs/shuttle-react'
|
||||
import { useEffect } from 'react'
|
||||
import { useLocation, useNavigate, useParams } from 'react-router-dom'
|
||||
|
||||
import WalletConnectButton from 'components/Wallet/WalletConnectButton'
|
||||
import WalletConnectedButton from 'components/Wallet/WalletConnectedButton'
|
||||
import WalletConnecting from 'components/Wallet/WalletConnecting'
|
||||
import useCurrentWallet from 'hooks/useCurrentWallet'
|
||||
import useStore from 'store'
|
||||
import { getPage, getRoute } from 'utils/route'
|
||||
@ -14,39 +13,22 @@ export default function Wallet() {
|
||||
const { address: addressInUrl } = useParams()
|
||||
const { pathname } = useLocation()
|
||||
const currentWallet = useCurrentWallet()
|
||||
const { simulate, sign, broadcast } = useShuttle()
|
||||
const address = useStore((s) => s.address)
|
||||
const client = useStore((s) => s.client)
|
||||
|
||||
// Set connection status
|
||||
useEffect(() => {
|
||||
const isConnected = !!currentWallet
|
||||
useStore.setState(
|
||||
isConnected
|
||||
? {
|
||||
address: currentWallet.account.address,
|
||||
}
|
||||
: { address: undefined, accounts: null, client: undefined },
|
||||
)
|
||||
}, [currentWallet])
|
||||
|
||||
// Set the client
|
||||
useEffect(() => {
|
||||
async function getCosmWasmClient() {
|
||||
if (client || !currentWallet) return
|
||||
const cosmClient = await CosmWasmClient.connect(currentWallet.network.rpc)
|
||||
const walletClient: WalletClient = {
|
||||
broadcast,
|
||||
cosmWasmClient: cosmClient,
|
||||
connectedWallet: currentWallet,
|
||||
sign,
|
||||
simulate,
|
||||
}
|
||||
useStore.setState({ client: walletClient })
|
||||
if (!currentWallet) {
|
||||
useStore.setState({ address: undefined, accounts: null, client: undefined })
|
||||
return
|
||||
}
|
||||
|
||||
getCosmWasmClient()
|
||||
}, [currentWallet, address, simulate, sign, broadcast, client])
|
||||
if (client) {
|
||||
if (currentWallet.account.address !== address)
|
||||
useStore.setState({ address: currentWallet.account.address })
|
||||
return
|
||||
}
|
||||
useStore.setState({ focusComponent: <WalletConnecting autoConnect /> })
|
||||
}, [currentWallet, client, address])
|
||||
|
||||
// Redirect when switching wallets or on first connection
|
||||
useEffect(() => {
|
||||
|
Loading…
Reference in New Issue
Block a user