Skip to content

Commit

Permalink
feat: claim rewards
Browse files Browse the repository at this point in the history
  • Loading branch information
swkatmask committed May 17, 2024
1 parent e504de5 commit 8ddb1ca
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 54 deletions.
7 changes: 5 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { createRouter, RouterProvider } from '@tanstack/react-router'
import { StrictMode } from 'react'

import { ChakraBaseProvider } from '@chakra-ui/react'
import { ChakraBaseProvider, ToastProviderProps } from '@chakra-ui/react'
import { i18n } from '@lingui/core'
import { I18nProvider } from '@lingui/react'
import { QueryClientProvider } from '@tanstack/react-query'
Expand All @@ -20,11 +20,14 @@ declare module '@tanstack/react-router' {
}
}

const toastOptions = {
defaultOptions: { position: 'top-right' },
} satisfies ToastProviderProps
export function App() {
return (
<StrictMode>
<I18nProvider i18n={i18n}>
<ChakraBaseProvider theme={theme}>
<ChakraBaseProvider theme={theme} toastOptions={toastOptions}>
<QueryClientProvider client={queryClient}>
<WagmiProvider>
<RouterProvider router={router} />
Expand Down
2 changes: 1 addition & 1 deletion src/components/StakeMaskStatusCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export const StakeMaskStatusCard: FC<StakeMaskStatusCardProps> = ({ ...props })
spacing={6}
>
{pool?.apr ? (
<Tooltip label={`${formatNumber(+pool.apr * 100, 18)}%`}>
<Tooltip label={`${formatNumber(+pool.apr * 100, 18)}%`} hasArrow placement="top">
<Box
h="56px"
fontSize="32px"
Expand Down
35 changes: 29 additions & 6 deletions src/components/UserStatus/RewardCard.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import { Box, Button, HStack, Stack } from '@chakra-ui/react'
import { Box, Button, HStack, Spinner, Stack, useToast } from '@chakra-ui/react'
import { t } from '@lingui/macro'
import { ActionCard, ActionCardProps } from './ActionCard'

import { useWriteContract } from 'wagmi'
import { rewardABI } from '../../abis/reward'
import { formatNumber } from '../../helpers/formatNumber'
import { PoolInfo } from '../../types/api'
import { useUserInfo } from '../../hooks/useUserInfo'
import { UserInfo } from '../../types/api'
import { ProgressiveText } from '../ProgressiveText'
import { TokenIcon } from '../TokenIcon'
import { ActionCard, ActionCardProps } from './ActionCard'

interface Props extends ActionCardProps {
reward?: PoolInfo['reward_pool'][string]
reward?: UserInfo['reward_pool'][number]
}

export function RewardCard({ reward, ...props }: Props) {
const { writeContractAsync, isPending } = useWriteContract()
const { data: userInfo, isLoading: loadingUserInfo } = useUserInfo()
const toast = useToast()
return (
<ActionCard display="flex" flexDir="column" {...props}>
<Stack alignItems="center" flexGrow={1}>
Expand Down Expand Up @@ -49,8 +54,26 @@ export function RewardCard({ reward, ...props }: Props) {
bg="gradient.purple"
_hover={{ bg: 'gradient.purple', transform: 'scale(1.01)' }}
_active={{ transform: 'scale(0.9)' }}
disabled={loadingUserInfo}
onClick={async () => {
if (!reward || !userInfo) return
const rewardPool = userInfo.reward_pool.find((x) => x.reward_pool_id === reward.reward_pool_id)
if (!rewardPool) {
toast({
status: 'error',
title: t`No match pool found.`,
})
return
}
const res = await writeContractAsync({

Check failure on line 68 in src/components/UserStatus/RewardCard.tsx

View workflow job for this annotation

GitHub Actions / eslint

'res' is assigned a value but never used
abi: rewardABI,
address: import.meta.env.REWARD_CONTRACT_ADDRESS,
functionName: 'claim',
args: [reward.reward_pool_id, BigInt(reward.big_amount), rewardPool.proof],
})
}}
>
{t`Claim`}
{isPending ? <Spinner size="sm" /> : t`Claim`}
</Button>
</Stack>
</ActionCard>
Expand Down
7 changes: 2 additions & 5 deletions src/components/UserStatus/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@ import { useUserInfo } from '../../hooks/useUserInfo'
import { RewardCard } from './RewardCard'
import { StakedMask } from './StakedMask'
import { UserTotalPoints } from './UserTotalPoint'
import { usePoolInfo } from '../../hooks/usePoolInfo'

export interface UserStatusProps extends GridProps {}

export function UserStatus(props: UserStatusProps) {
const { data: userInfo } = useUserInfo()
const { data: pool } = usePoolInfo()
const rewardTokens = pool ? Object.values(pool.reward_pool) : []
const rss3 = rewardTokens.find((x) => x.name === 'rss3')
const ton = rewardTokens.find((x) => x.name === 'ton')
const rss3 = userInfo?.reward_pool.find((x) => x.name === 'rss3')
const ton = userInfo?.reward_pool.find((x) => x.name === 'ton')

if (!userInfo)
return (
Expand Down
27 changes: 13 additions & 14 deletions src/hooks/useLinkTwitter.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
import { useToast } from '@chakra-ui/react'
import { useAsyncFn } from 'react-use'
import urlcat from 'urlcat'
import { useAccount, useClient } from 'wagmi'
import { signMessage } from 'wagmi/actions'
import { config } from '../configs/wagmiClient'
import { UserRejectedRequestError } from 'viem'
import { useAccount, useSignMessage } from 'wagmi'
import { FIREFLY_API_ROOT } from '../constants/api'
import { fetchJSON } from '../helpers/fetchJSON'
import { TwitterAuthorizeResponse } from '../types/api'
import { useToast } from '@chakra-ui/react'
import { UserRejectedRequestError } from 'viem'

// Any message is ok.
const message = 'Hello, world!'
const message = 'Stake $MASK'
export function useLinkTwitter() {
const account = useAccount()
const client = useClient()
const toast = useToast()
const { signMessageAsync } = useSignMessage()

return useAsyncFn(async () => {
if (!account.address || !client) return
if (!account.address) return
try {
const signed = await signMessage(config, {
account: account.address,
message: message,
})
const signed = await signMessageAsync({ message })
const url = urlcat(FIREFLY_API_ROOT, '/v1/mask_stake/twitter/authorize', {
original_message: message,
signature_message: signed.slice(2), // omit 0x
Expand All @@ -31,19 +26,23 @@ export function useLinkTwitter() {
const res = await fetchJSON<TwitterAuthorizeResponse>(url)
if (res.code !== 200) {
console.error('Failed to get twitter authorize', res.message, res.reason)
toast({
status: 'error',
title: 'Failed to get twitter authorize',
description: res.message,
})
return
}
location.href = res.data.url
} catch (err) {
if (err instanceof UserRejectedRequestError) {
toast({
status: 'error',
position: 'top-right',
title: err.details,
})
return
}
throw err
}
}, [account.address, client])
}, [account.address, signMessageAsync])
}
21 changes: 5 additions & 16 deletions src/modals/BaseModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
DrawerContent,
DrawerHeader,
DrawerOverlay,
IconButton,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalContentProps,
ModalHeader,
Expand All @@ -16,30 +16,19 @@ import {
useBreakpointValue,
} from '@chakra-ui/react'

import { t } from '@lingui/macro'
import { ReactNode } from 'react'
import Close from '../assets/close.svg?react'

interface Props extends ModalProps {
title: ReactNode
width: ModalContentProps['width']
height: ModalContentProps['height']
}
export function BaseModal({ title, width, height, ...rest }: Props) {
export function BaseModal({ title, width, ...rest }: Props) {
const isMobile = useBreakpointValue({ base: true, md: false })
const header = (
<>
<Text fontSize="32px">{title}</Text>
<IconButton
rounded="50%"
border="1px solid "
borderColor="neutrals.6"
bg="transparent"
aria-label={t`Close`}
ml="auto"
icon={<Close />}
onClick={rest.onClose}
/>
<ModalCloseButton />
</>
)
if (isMobile) {
Expand All @@ -62,8 +51,8 @@ export function BaseModal({ title, width, height, ...rest }: Props) {
return (
<Modal isCentered {...rest}>
<ModalOverlay />
<ModalContent bg="neutrals.8" rounded={20} width={width} height={height} maxW="auto" maxH="auto">
<ModalHeader display="flex" flexDir="row" padding="16px 16px 0 16px">
<ModalContent bg="neutrals.8" rounded={20} width={width} maxW="auto" maxH="auto">
<ModalHeader display="flex" flexDir="row" padding="24px 24px 0 24px">
{header}
</ModalHeader>
<ModalBody p={6} display="flex" flexDir="column">
Expand Down
10 changes: 5 additions & 5 deletions src/modals/UITaskManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ export interface BaseDialogProps<T> extends Pick<ModalProps, 'isOpen' | 'onClose
}

/**
* Create a manager of small UI task sessions,
* which provides both a Context and a Provider.
* Create a manager of UI task sessions,
*/
export const createUITaskManager = <TaskOptions extends BaseDialogProps<Result>, Result>(
Component: ComponentType<TaskOptions>,
Expand Down Expand Up @@ -59,10 +58,10 @@ export const createUITaskManager = <TaskOptions extends BaseDialogProps<Result>,
show(options?: Omit<TaskOptions, 'isOpen'>, signal?: AbortSignal) {
const [promise, resolve, reject] = defer<Result | null>()
id += 1
signal?.addEventListener('abort', function abortHandler() {
function abortHandler() {
resolve(null)
signal.removeEventListener('abort', abortHandler)
})
}
signal?.addEventListener('abort', abortHandler, { once: true })
const newTask: Task = {
id,
isOpen: true,
Expand All @@ -73,6 +72,7 @@ export const createUITaskManager = <TaskOptions extends BaseDialogProps<Result>,
}
setTasks((list) => [...list, newTask])
promise.then(() => {
signal?.removeEventListener('abort', abortHandler)
removeTask(newTask.id)
})
return promise
Expand Down
2 changes: 0 additions & 2 deletions src/styles/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import { Drawer } from './components/Drawer.ts'

window.localStorage.setItem('chakra-ui-color-mode', 'dark')

console.log(chakraTheme.components.Tooltip)

export const theme = extendBaseTheme({
components: {
...chakraTheme.components,
Expand Down
6 changes: 3 additions & 3 deletions src/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ export interface UserInfo {
twitter_display_name: string
twitter_image: string
address_type: string
reward_pool: {
reward_pool: Array<{
reward_pool_id: number
amount: string
big_amount: string
/** token name */
name: string
/** Merkle tree */
proof: string[]
}
proof: Array<`0x${string}`>
}>
}

export type UserInfoResponse = Response<UserInfo>
Expand Down

0 comments on commit 8ddb1ca

Please sign in to comment.