mars-v2-frontend/src/components/Wallet/WalletSelect.tsx
Linkie Link cec9e50955
fix: fixed the wallet auto connection (#341)
* fix: fixed the wallet auto connection

* tidy: refactor

* fix: re-enabled account change support

* tidy: refactor
2023-08-05 11:11:07 +02:00

192 lines
5.9 KiB
TypeScript

import { useShuttle } from '@delphi-labs/shuttle-react'
import Image from 'next/image'
import React, { useEffect, useState } from 'react'
import QRCode from 'react-qr-code'
import Button from 'components/Button'
import FullOverlayContent from 'components/FullOverlayContent'
import { ChevronLeft, ChevronRight } from 'components/Icons'
import Text from 'components/Text'
import WalletConnecting from 'components/Wallet/WalletConnecting'
import { CHAINS } from 'constants/chains'
import { ENV } from 'constants/env'
import { WALLETS } from 'constants/wallets'
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
handleClick: () => void
}
const currentChainId = ENV.CHAIN_ID
const currentChain = CHAINS[currentChainId]
function WalletOption(props: WalletOptionProps) {
return (
<Button
color='tertiary'
className='flex w-full !justify-start px-4 py-3'
onClick={props.handleClick}
>
<Image
className='rounded-full'
width={20}
height={20}
src={props.imageSrc}
alt={props.name}
/>
<Text className='ml-2 flex-1 text-left'>{props.name}</Text>
<ChevronRight className='h-4 w-4' />
</Button>
)
}
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 = (extensionProviderId: string) => {
useStore.setState({
focusComponent: <WalletConnecting providerId={extensionProviderId} />,
})
}
const handleMobileConnectClick = async (mobileProviderId: string, chainId: string) => {
try {
const urls = await mobileConnect({
mobileProviderId,
chainId,
})
if (isMobile()) {
if (isAndroid()) {
window.location.href = urls.androidUrl
} else if (isIOS()) {
window.location.href = urls.iosUrl
} else {
window.location.href = urls.androidUrl
}
} else {
setQRCodeUrl(urls.qrCodeUrl)
}
} catch (error) {
if (error instanceof Error) {
setError({ title: 'Failed to connect to wallet', message: error.message })
}
}
}
useEffect(() => {
if (error?.message && error?.title) {
useStore.setState({
toast: {
isError: true,
title: error.title,
message: error.message,
},
})
}
}, [error?.message, error?.title])
if (qrCodeUrl)
return (
<FullOverlayContent
title={'Scan the QR Code'}
copy={
'Open your mobile wallet App and use the QR Scan function to connect via WalletConnect v2'
}
button={{
color: 'secondary',
leftIcon: <ChevronLeft />,
iconClassName: 'w-3',
onClick: () => setQRCodeUrl(''),
text: 'Back',
}}
>
<div className='mb-4 rounded-sm bg-white p-2'>
<QRCode value={qrCodeUrl} />
</div>
</FullOverlayContent>
)
return (
<FullOverlayContent
title={'Connect your wallet'}
copy={`Deposit assets from your ${currentChain.name} address to your Mars credit account.`}
docs='wallet'
>
<div className='flex w-full flex-wrap gap-3'>
{!isMobile() && (
<>
{sortedExtensionProviders.map((provider) => {
const walletId = provider.id as WalletID
return (
<React.Fragment key={walletId}>
{Array.from(provider.networks.values())
.filter((network) => network.chainId === currentChainId)
.map((network) => {
if (!provider.initialized && !provider.initializing) {
return (
<WalletOption
key={`${walletId}-${network.chainId}`}
handleClick={() => {
window.open(WALLETS[walletId].installURL ?? '/', '_blank')
}}
imageSrc={WALLETS[walletId].imageURL}
name={WALLETS[walletId].install ?? 'Install Wallet'}
/>
)
}
return (
<WalletOption
key={`${walletId}-${network.chainId}`}
handleClick={() => handleConnectClick(walletId)}
imageSrc={WALLETS[walletId].imageURL}
name={WALLETS[walletId].name ?? 'Conenct Wallet'}
/>
)
})}
</React.Fragment>
)
})}
</>
)}
{mobileProviders.map((provider) => {
const walletId = provider.id as WalletID
return (
<React.Fragment key={walletId}>
{Array.from(provider.networks.values())
.filter((network) => network.chainId === currentChainId)
.map((network) => {
return (
<WalletOption
key={`${walletId}-${network.chainId}`}
name={WALLETS[walletId].walletConnect ?? 'WalletConnect'}
imageSrc={WALLETS[walletId].mobileImageURL ?? '/'}
handleClick={() => handleMobileConnectClick(walletId, network.chainId)}
/>
)
})}
</React.Fragment>
)
})}
</div>
</FullOverlayContent>
)
}