mango-v4-ui/components/shared/ToggleFollowButton.tsx

146 lines
4.2 KiB
TypeScript
Raw Normal View History

2023-11-13 20:41:16 -08:00
import { bs58 } from '@project-serum/anchor/dist/cjs/utils/bytes'
import { PublicKey } from '@solana/web3.js'
import {
QueryObserverResult,
RefetchOptions,
RefetchQueryFilters,
} from '@tanstack/react-query'
import { MANGO_DATA_API_URL } from 'utils/constants'
import { notify } from 'utils/notifications'
import { StarIcon as FilledStarIcon } from '@heroicons/react/20/solid'
import { StarIcon } from '@heroicons/react/24/outline'
import { useWallet } from '@solana/wallet-adapter-react'
import useFollowedAccounts from 'hooks/useFollowedAccounts'
import Tooltip from './Tooltip'
import { useTranslation } from 'react-i18next'
2023-11-14 15:53:34 -08:00
import { useMemo, useState } from 'react'
2023-11-14 02:39:37 -08:00
import { FollowedAccountApi } from '@components/explore/FollowedAccounts'
2023-11-14 15:53:34 -08:00
import Loading from './Loading'
2023-11-13 20:41:16 -08:00
const toggleFollowAccount = async (
2023-11-14 02:39:37 -08:00
type: string,
2023-11-13 20:41:16 -08:00
mangoAccountPk: string,
publicKey: PublicKey | null,
signMessage: (message: Uint8Array) => Promise<Uint8Array>,
refetch: <TPageData>(
options?: (RefetchOptions & RefetchQueryFilters<TPageData>) | undefined,
) => Promise<QueryObserverResult>,
2023-11-14 15:53:34 -08:00
setLoading: (loading: boolean) => void,
2023-11-13 20:41:16 -08:00
) => {
try {
if (!publicKey) throw new Error('Wallet not connected!')
if (!signMessage) throw new Error('Wallet does not support message signing')
2023-11-14 15:53:34 -08:00
setLoading(true)
2023-11-13 20:41:16 -08:00
const messageObject = {
mango_account: mangoAccountPk,
action: type,
}
const messageString = JSON.stringify(messageObject)
const message = new TextEncoder().encode(messageString)
const signature = await signMessage(message)
2023-11-14 02:39:37 -08:00
const isPost = type === 'insert'
const method = isPost ? 'POST' : 'DELETE'
2023-11-13 20:41:16 -08:00
const requestOptions = {
method: method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
wallet_pk: publicKey.toString(),
message: messageString,
signature: bs58.encode(signature),
}),
}
const response = await fetch(
`${MANGO_DATA_API_URL}/user-data/following`,
requestOptions,
)
if (response.status === 200) {
await refetch()
}
} catch {
notify({ type: 'error', title: 'Failed to follow account' })
2023-11-14 15:53:34 -08:00
} finally {
setLoading(false)
2023-11-13 20:41:16 -08:00
}
}
const ToggleFollowButton = ({
2023-11-14 02:39:37 -08:00
accountPk,
2023-11-13 20:41:16 -08:00
showText,
}: {
2023-11-14 02:39:37 -08:00
accountPk: string
2023-11-13 20:41:16 -08:00
showText?: boolean
}) => {
const { t } = useTranslation('account')
const { publicKey, signMessage } = useWallet()
2023-11-14 02:39:37 -08:00
const { data: followedAccounts, refetch: refetchFollowedAccounts } =
useFollowedAccounts()
2023-11-14 15:53:34 -08:00
const [loading, setLoading] = useState(false)
2023-11-14 02:39:37 -08:00
const [isFollowed, type] = useMemo(() => {
if (!followedAccounts || !followedAccounts.length) return [false, 'insert']
const followed = followedAccounts.find(
(acc: FollowedAccountApi) => acc.mango_account === accountPk,
)
if (followed) {
return [true, 'delete']
} else return [false, 'insert']
}, [accountPk, followedAccounts])
2023-11-14 15:53:34 -08:00
const disabled =
!accountPk ||
loading ||
!publicKey ||
!signMessage ||
2023-12-02 04:26:39 -08:00
(!isFollowed && followedAccounts && followedAccounts?.length >= 10)
2023-11-14 15:53:34 -08:00
2023-11-13 20:41:16 -08:00
return (
<Tooltip
content={
2023-11-14 16:08:22 -08:00
!publicKey
? t('account:tooltip-connect-to-follow')
2023-12-02 04:26:39 -08:00
: !isFollowed && followedAccounts && followedAccounts?.length >= 10
2023-11-14 02:39:37 -08:00
? t('account:tooltip-follow-max-reached')
: showText
2023-11-13 20:41:16 -08:00
? ''
: isFollowed
? t('account:tooltip-unfollow-account')
: t('account:tooltip-follow-account')
}
>
<button
2023-11-14 02:39:37 -08:00
className="flex items-center focus:outline-none disabled:opacity-50 md:hover:text-th-fgd-3"
2023-11-14 15:53:34 -08:00
disabled={disabled}
2023-11-13 20:41:16 -08:00
onClick={() =>
toggleFollowAccount(
type,
2023-11-14 02:39:37 -08:00
accountPk,
2023-11-13 20:41:16 -08:00
publicKey,
signMessage!,
refetchFollowedAccounts,
2023-11-14 15:53:34 -08:00
setLoading,
2023-11-13 20:41:16 -08:00
)
}
>
2023-11-14 15:53:34 -08:00
{loading ? (
<Loading />
) : isFollowed ? (
<FilledStarIcon className="h-5 w-5 text-th-active" />
2023-11-13 20:41:16 -08:00
) : (
2023-11-14 15:53:34 -08:00
<StarIcon className="h-5 w-5 text-th-fgd-3" />
2023-11-13 20:41:16 -08:00
)}
{showText ? (
<span className="ml-1.5">
{isFollowed ? t('unfollow') : t('follow')}
</span>
) : null}
</button>
</Tooltip>
)
}
export default ToggleFollowButton