feat: 董事会
This commit is contained in:
parent
977b6fd61b
commit
14009878b3
|
|
@ -48,6 +48,7 @@ const Pool = lazy(() => import('./views/Pool'))
|
||||||
const PoolFinder = lazy(() => import('./views/PoolFinder'))
|
const PoolFinder = lazy(() => import('./views/PoolFinder'))
|
||||||
const RemoveLiquidity = lazy(() => import('./views/RemoveLiquidity'))
|
const RemoveLiquidity = lazy(() => import('./views/RemoveLiquidity'))
|
||||||
const Referral = lazy(() => import('./views/Referral'))
|
const Referral = lazy(() => import('./views/Referral'))
|
||||||
|
const Board = lazy(() => import('./views/Board'))
|
||||||
|
|
||||||
// This config is required for number formatting
|
// This config is required for number formatting
|
||||||
BigNumber.config({
|
BigNumber.config({
|
||||||
|
|
@ -89,6 +90,9 @@ const App: React.FC = () => {
|
||||||
<Route path="/referral">
|
<Route path="/referral">
|
||||||
<Referral />
|
<Referral />
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route path="/board">
|
||||||
|
<Board />
|
||||||
|
</Route>
|
||||||
{/* <Route path="/lottery">
|
{/* <Route path="/lottery">
|
||||||
<Lottery />
|
<Lottery />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export const CACHE_TOKEN = 'token'
|
export const CACHE_TOKEN = 'token'
|
||||||
export const CACHE_USERIFNO = 'userInfo'
|
export const CACHE_USERINFO = 'userInfo'
|
||||||
export const CACHE_ACCOUNT = 'account'
|
export const CACHE_ACCOUNT = 'account'
|
||||||
export const CACHE_INVITE_CODE = 'inviteCode'
|
export const CACHE_INVITE_CODE = 'inviteCode'
|
||||||
|
|
|
||||||
|
|
@ -33,3 +33,4 @@ export const LOTTERY_TICKET_PRICE = 1
|
||||||
export const DEFAULT_TOKEN_DECIMAL = BIG_TEN.pow(18)
|
export const DEFAULT_TOKEN_DECIMAL = BIG_TEN.pow(18)
|
||||||
export const DEFAULT_GAS_LIMIT = 200000
|
export const DEFAULT_GAS_LIMIT = 200000
|
||||||
export const DEFAULT_GAS_PRICE = 5
|
export const DEFAULT_GAS_PRICE = 5
|
||||||
|
export const TOKEN_SYMBOL = 'HCC'
|
||||||
|
|
|
||||||
|
|
@ -206,18 +206,18 @@ export const useBoards = (): Boards[] => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useBoardsFromPid = (pid): Boards => {
|
export const useBoardsFromPid = (pid): Boards => {
|
||||||
const node = useSelector((state: State) => state.boards.data.find((p) => p.pid === pid))
|
const board = useSelector((state: State) => state.boards.data.find((p) => p.pid === pid))
|
||||||
return node
|
return board
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useNodeUser = (pid) => {
|
export const useBoardUser = (pid) => {
|
||||||
const node = useBoardsFromPid(pid)
|
const board = useBoardsFromPid(pid)
|
||||||
return {
|
return {
|
||||||
allowance: node.userData ? new BigNumber(node.userData.allowance) : new BigNumber(0),
|
allowance: board.userData ? new BigNumber(board.userData.allowance) : new BigNumber(0),
|
||||||
tokenBalance: node.userData ? new BigNumber(node.userData.tokenBalance) : new BigNumber(0),
|
tokenBalance: board.userData ? new BigNumber(board.userData.tokenBalance) : new BigNumber(0),
|
||||||
stakedBalance: node.userData ? new BigNumber(node.userData.stakedBalance) : new BigNumber(0),
|
stakedBalance: board.userData ? new BigNumber(board.userData.stakedBalance) : new BigNumber(0),
|
||||||
unlockTime: node.userData ? node.userData.unlockTime : 0,
|
unlockTime: board.userData ? board.userData.unlockTime : 0,
|
||||||
xCandyBalance: node.userData ? node.userData.xCandyBalance : 0,
|
xCandyBalance: board.userData ? board.userData.xCandyBalance : 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// cake
|
// cake
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
|
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
|
||||||
import { queryUserInfo } from 'services/user'
|
import { queryUserInfo } from 'services/user'
|
||||||
import { CACHE_TOKEN, CACHE_ACCOUNT, CACHE_USERIFNO } from 'config/constants/cacheKey'
|
import { CACHE_TOKEN, CACHE_ACCOUNT, CACHE_USERINFO } from 'config/constants/cacheKey'
|
||||||
import multicall from 'utils/multicall'
|
import multicall from 'utils/multicall'
|
||||||
// import inviteAbi from 'config/abi/invite.json'
|
// import inviteAbi from 'config/abi/invite.json'
|
||||||
// import { getInviteAddress } from 'utils/addressHelpers'
|
// import { getInviteAddress } from 'utils/addressHelpers'
|
||||||
|
|
@ -39,7 +39,7 @@ export const userInfoSlice = createSlice({
|
||||||
state.account = info.address
|
state.account = info.address
|
||||||
info.token && (state.token = info.token)
|
info.token && (state.token = info.token)
|
||||||
localStorage.setItem(CACHE_TOKEN, state.token)
|
localStorage.setItem(CACHE_TOKEN, state.token)
|
||||||
localStorage.setItem(CACHE_USERIFNO, JSON.stringify(info))
|
localStorage.setItem(CACHE_USERINFO, JSON.stringify(info))
|
||||||
localStorage.setItem(CACHE_ACCOUNT, info.address)
|
localStorage.setItem(CACHE_ACCOUNT, info.address)
|
||||||
},
|
},
|
||||||
clearUserInfo: (state) => {
|
clearUserInfo: (state) => {
|
||||||
|
|
@ -47,14 +47,14 @@ export const userInfoSlice = createSlice({
|
||||||
state.account = ''
|
state.account = ''
|
||||||
state.token = ''
|
state.token = ''
|
||||||
localStorage.removeItem(CACHE_TOKEN)
|
localStorage.removeItem(CACHE_TOKEN)
|
||||||
localStorage.removeItem(CACHE_USERIFNO)
|
localStorage.removeItem(CACHE_USERINFO)
|
||||||
localStorage.removeItem(CACHE_ACCOUNT)
|
localStorage.removeItem(CACHE_ACCOUNT)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
extraReducers: (builder) => {
|
extraReducers: (builder) => {
|
||||||
builder.addCase(fetchUserInfo.fulfilled, (state, action) => {
|
builder.addCase(fetchUserInfo.fulfilled, (state, action) => {
|
||||||
state.userInfo = action.payload
|
state.userInfo = action.payload
|
||||||
localStorage.setItem(CACHE_USERIFNO, JSON.stringify(state.userInfo))
|
localStorage.setItem(CACHE_USERINFO, JSON.stringify(state.userInfo))
|
||||||
})
|
})
|
||||||
// .addCase(fetchUserInviteInfo.fulfilled, (state, action) => {
|
// .addCase(fetchUserInviteInfo.fulfilled, (state, action) => {
|
||||||
// state.userInfo = { ...state.userInfo, invite_reward: action.payload }
|
// state.userInfo = { ...state.userInfo, invite_reward: action.payload }
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import styled, { keyframes } from 'styled-components'
|
||||||
import { Flex, Text, Skeleton } from '@pancakeswap/uikit'
|
import { Flex, Text, Skeleton } from '@pancakeswap/uikit'
|
||||||
import { provider as ProviderType } from 'web3-core'
|
import { provider as ProviderType } from 'web3-core'
|
||||||
import { getBoardAddress } from 'utils/addressHelpers'
|
import { getBoardAddress } from 'utils/addressHelpers'
|
||||||
import useI18n from 'hooks/useI18n'
|
import { useTranslation } from 'contexts/Localization'
|
||||||
import ExpandableSectionButton from 'components/ExpandableSectionButton'
|
import ExpandableSectionButton from 'components/ExpandableSectionButton'
|
||||||
import DetailsSection from './DetailsSection'
|
import DetailsSection from './DetailsSection'
|
||||||
import CardHeading from './CardHeading'
|
import CardHeading from './CardHeading'
|
||||||
|
|
@ -63,7 +63,7 @@ const FCard = styled.div`
|
||||||
`
|
`
|
||||||
|
|
||||||
const Divider = styled.div`
|
const Divider = styled.div`
|
||||||
background-color: ${({ theme }) => theme.colors.borderColor};
|
background-color: ${({ theme }) => theme.colors.cardBorder};
|
||||||
height: 1px;
|
height: 1px;
|
||||||
margin: 28px auto;
|
margin: 28px auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
@ -75,22 +75,22 @@ const ExpandingWrapper = styled.div<{ expanded: boolean }>`
|
||||||
`
|
`
|
||||||
|
|
||||||
interface NodeCardProps {
|
interface NodeCardProps {
|
||||||
node: any
|
board: any
|
||||||
removed: boolean
|
removed: boolean
|
||||||
provider?: ProviderType
|
provider?: ProviderType
|
||||||
account?: string
|
account?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const NodeCard: React.FC<NodeCardProps> = ({ node, account }) => {
|
const NodeCard: React.FC<NodeCardProps> = ({ board, account }) => {
|
||||||
const TranslateString = useI18n()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const [showExpandableSection, setShowExpandableSection] = useState(false)
|
const [showExpandableSection, setShowExpandableSection] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FCard>
|
<FCard>
|
||||||
{/* {true && <StyledCardAccent />} */}
|
{/* {true && <StyledCardAccent />} */}
|
||||||
<CardHeading name={TranslateString(node.stringId, node.name)} img={node.img} tokenSymbol={node.tokenSymbol} />
|
<CardHeading name={t(board.name)} img={board.img} tokenSymbol={board.tokenSymbol} />
|
||||||
<CardActionsContainer node={node} account={account} />
|
<CardActionsContainer node={board} account={account} />
|
||||||
<Divider />
|
<Divider />
|
||||||
<ExpandableSectionButton
|
<ExpandableSectionButton
|
||||||
onClick={() => setShowExpandableSection(!showExpandableSection)}
|
onClick={() => setShowExpandableSection(!showExpandableSection)}
|
||||||
|
|
@ -99,7 +99,7 @@ const NodeCard: React.FC<NodeCardProps> = ({ node, account }) => {
|
||||||
<ExpandingWrapper expanded={showExpandableSection}>
|
<ExpandingWrapper expanded={showExpandableSection}>
|
||||||
<DetailsSection
|
<DetailsSection
|
||||||
bscScanAddress={`${process.env.REACT_APP_NETWORK_URL}/address/${getBoardAddress()}`}
|
bscScanAddress={`${process.env.REACT_APP_NETWORK_URL}/address/${getBoardAddress()}`}
|
||||||
totalValueFormated={node.tokenBalance || '-'}
|
totalValueFormated={board.tokenBalance || '-'}
|
||||||
/>
|
/>
|
||||||
</ExpandingWrapper>
|
</ExpandingWrapper>
|
||||||
</FCard>
|
</FCard>
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,15 @@ import BigNumber from 'bignumber.js'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { provider as ProviderType } from 'web3-core'
|
import { provider as ProviderType } from 'web3-core'
|
||||||
import { getAddress } from 'utils/addressHelpers'
|
import { getAddress } from 'utils/addressHelpers'
|
||||||
import { getBep20Contract } from 'utils/contractHelpers'
|
|
||||||
import { Button, Flex, Text } from '@pancakeswap/uikit'
|
import { Button, Flex, Text } from '@pancakeswap/uikit'
|
||||||
|
import { useTranslation } from 'contexts/Localization'
|
||||||
import { Boards } from 'state/types'
|
import { Boards } from 'state/types'
|
||||||
import { useBoardUser } from 'state/hooks'
|
import { useBoardUser } from 'state/hooks'
|
||||||
import { TOKEN_SYMBOL2 } from 'config/index'
|
import { TOKEN_SYMBOL } from 'config/index'
|
||||||
import { getBalanceNumber } from 'utils/formatBalance'
|
import { getBalanceNumber } from 'utils/formatBalance'
|
||||||
import useI18n from 'hooks/useI18n'
|
import { useERC20 } from 'hooks/useContract'
|
||||||
import useWeb3 from 'hooks/useWeb3'
|
|
||||||
import { useNodeApprove } from 'hooks/useApprove'
|
|
||||||
import UnlockButton from 'components/UnlockButton'
|
import UnlockButton from 'components/UnlockButton'
|
||||||
|
import useApproveBoard from '../../hooks/useApproveBoard'
|
||||||
import StakeAction from './StakeAction'
|
import StakeAction from './StakeAction'
|
||||||
|
|
||||||
const Action = styled.div`
|
const Action = styled.div`
|
||||||
|
|
@ -26,16 +25,14 @@ interface NodeCardActionsProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const CardActions: React.FC<NodeCardActionsProps> = ({ node, account }) => {
|
const CardActions: React.FC<NodeCardActionsProps> = ({ node, account }) => {
|
||||||
const TranslateString = useI18n()
|
const { t } = useTranslation()
|
||||||
const [requestedApproval, setRequestedApproval] = useState(false)
|
const [requestedApproval, setRequestedApproval] = useState(false)
|
||||||
const pid = node.pid
|
const pid = node.pid
|
||||||
const { allowance, tokenBalance, stakedBalance, xCandyBalance } = useBoardUser(pid)
|
const { allowance, tokenBalance, stakedBalance, xCandyBalance } = useBoardUser(pid)
|
||||||
const isApproved = account && allowance && allowance.isGreaterThan(0)
|
const isApproved = account && allowance && allowance.isGreaterThan(0)
|
||||||
const web3 = useWeb3()
|
const tokenContract = useERC20(getAddress(node.tokenAddresses))
|
||||||
const tokenAddress = getAddress(node.tokenAddresses)
|
|
||||||
const tokenContract = getBep20Contract(tokenAddress, web3)
|
|
||||||
|
|
||||||
const { onApprove } = useNodeApprove(tokenContract)
|
const { onApprove } = useApproveBoard(tokenContract)
|
||||||
|
|
||||||
const handleApprove = useCallback(async () => {
|
const handleApprove = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -54,10 +51,10 @@ const CardActions: React.FC<NodeCardActionsProps> = ({ node, account }) => {
|
||||||
<Flex flexDirection="column" alignItems="flex-start" mt="10">
|
<Flex flexDirection="column" alignItems="flex-start" mt="10">
|
||||||
<Flex>
|
<Flex>
|
||||||
<Text bold textTransform="uppercase" color="secondary" fontSize="12px" pr="3px">
|
<Text bold textTransform="uppercase" color="secondary" fontSize="12px" pr="3px">
|
||||||
{TOKEN_SYMBOL2}
|
{TOKEN_SYMBOL}
|
||||||
</Text>
|
</Text>
|
||||||
<Text color="textSubtle" fontSize="12px">
|
<Text color="textSubtle" fontSize="12px">
|
||||||
{TranslateString(101018, 'Amount')}
|
{t('Amount')}
|
||||||
</Text>
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Text bold textTransform="uppercase" fontSize="20px">
|
<Text bold textTransform="uppercase" fontSize="20px">
|
||||||
|
|
@ -67,7 +64,7 @@ const CardActions: React.FC<NodeCardActionsProps> = ({ node, account }) => {
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Button mt="8px" width="100%" disabled={requestedApproval} onClick={handleApprove}>
|
<Button mt="8px" width="100%" disabled={requestedApproval} onClick={handleApprove}>
|
||||||
{TranslateString(758, 'Approve Contract')}
|
{t('Approve Contract')}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -79,7 +76,7 @@ const CardActions: React.FC<NodeCardActionsProps> = ({ node, account }) => {
|
||||||
{node.tokenSymbol}
|
{node.tokenSymbol}
|
||||||
</Text>
|
</Text>
|
||||||
<Text bold textTransform="uppercase" color="textSubtle" fontSize="12px">
|
<Text bold textTransform="uppercase" color="textSubtle" fontSize="12px">
|
||||||
{TranslateString(101004, 'Staked')}
|
{t('Staked')}
|
||||||
</Text>
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
{!account ? <UnlockButton mt="8px" width="100%" /> : renderApprovalOrStakeButton()}
|
{!account ? <UnlockButton mt="8px" width="100%" /> : renderApprovalOrStakeButton()}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { Tag, Flex, Heading, Image } from '@pancakeswap/uikit'
|
import { Tag, Flex, Heading, Image } from '@pancakeswap/uikit'
|
||||||
import Question from 'components/QuestionHelper'
|
import Question from 'components/QuestionHelper'
|
||||||
import useI18n from 'hooks/useI18n'
|
import { useTranslation } from 'contexts/Localization'
|
||||||
|
|
||||||
export interface ExpandableSectionProps {
|
export interface ExpandableSectionProps {
|
||||||
name?: string
|
name?: string
|
||||||
|
|
@ -18,15 +18,13 @@ const Wrapper = styled(Flex)`
|
||||||
`
|
`
|
||||||
|
|
||||||
const CardHeading: React.FC<ExpandableSectionProps> = ({ name, img, tokenSymbol }) => {
|
const CardHeading: React.FC<ExpandableSectionProps> = ({ name, img, tokenSymbol }) => {
|
||||||
const TranslateString = useI18n()
|
const { t } = useTranslation()
|
||||||
return (
|
return (
|
||||||
<Wrapper justifyContent="space-between" alignItems="center" mb="12px">
|
<Wrapper justifyContent="space-between" alignItems="center" mb="12px">
|
||||||
<Image src={`/images/nodes/${img}.png`} width={64} height={64} />
|
<Image src={`/images/nodes/${img}.png`} width={64} height={64} />
|
||||||
<Flex>
|
<Flex>
|
||||||
<Heading mb="4px">{name}</Heading>
|
<Heading mb="4px">{name}</Heading>
|
||||||
<Question
|
<Question text={t('To join board, you need to stake at least 0.1% total supply of Token')} />
|
||||||
text={TranslateString(101017, 'To join board, you need to stake at least 0.1% total supply of Token')}
|
|
||||||
/>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import useI18n from 'hooks/useI18n'
|
import { useTranslation } from 'contexts/Localization'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { Text, Flex, Link, LinkExternal } from '@pancakeswap/uikit'
|
import { Text, Flex, Link, LinkExternal } from '@pancakeswap/uikit'
|
||||||
|
|
||||||
|
|
@ -29,18 +29,18 @@ const StyledLinkExternal = styled(LinkExternal)`
|
||||||
`
|
`
|
||||||
|
|
||||||
const DetailsSection: React.FC<ExpandableSectionProps> = ({ bscScanAddress, removed, totalValueFormated }) => {
|
const DetailsSection: React.FC<ExpandableSectionProps> = ({ bscScanAddress, removed, totalValueFormated }) => {
|
||||||
const TranslateString = useI18n()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Flex justifyContent="space-between">
|
<Flex justifyContent="space-between">
|
||||||
<Text>{TranslateString(101010, 'Total Staked')}:</Text>
|
<Text>{t('Total Staked')}:</Text>
|
||||||
<Text>{totalValueFormated}</Text>
|
<Text>{totalValueFormated}</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
{/* )} */}
|
{/* )} */}
|
||||||
<Flex justifyContent="flex-start">
|
<Flex justifyContent="flex-start">
|
||||||
<Link external href={bscScanAddress} bold={false}>
|
<Link external href={bscScanAddress} bold={false}>
|
||||||
{TranslateString(356, 'View on BscScan')}
|
{t( 'View on BscScan')}
|
||||||
</Link>
|
</Link>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
import React, { useMemo } from 'react'
|
import React, { useMemo } from 'react'
|
||||||
import dayjs from 'dayjs'
|
// import dayjs from 'dayjs'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import BigNumber from 'bignumber.js'
|
import BigNumber from 'bignumber.js'
|
||||||
import { Button, Flex, Heading, IconButton, AddIcon, MinusIcon, useModal } from '@pancakeswap/uikit'
|
import { Button, Flex, Heading, IconButton, AddIcon, MinusIcon, useModal } from '@pancakeswap/uikit'
|
||||||
import useI18n from 'hooks/useI18n'
|
|
||||||
import { useNodeStake } from 'hooks/useStake'
|
// import { NODE_UNLOCK_TIME } from 'config/index'
|
||||||
import { useNodeUnstake } from 'hooks/useUnstake'
|
import { getBalanceNumber } from 'utils/formatBalance'
|
||||||
import { NODE_UNLOCK_TIME } from 'config/index'
|
|
||||||
import { getBalanceNumber, getFullDisplayBalance } from 'utils/formatBalance'
|
|
||||||
import { useBoardsFromPid } from 'state/hooks'
|
import { useBoardsFromPid } from 'state/hooks'
|
||||||
|
import { useTranslation } from 'contexts/Localization'
|
||||||
import useToast from 'hooks/useToast'
|
import useToast from 'hooks/useToast'
|
||||||
import DepositModal from '../DepositModal'
|
import DepositModal from '../DepositModal'
|
||||||
|
import useStakeBoard from '../../hooks/useStakeBoard'
|
||||||
|
import useUnstakeBoard from '../../hooks/useUnstakeBoard'
|
||||||
import WithdrawModal from '../WithdrawModal'
|
import WithdrawModal from '../WithdrawModal'
|
||||||
|
|
||||||
interface NodeCardActionsProps {
|
interface NodeCardActionsProps {
|
||||||
|
|
@ -28,10 +29,10 @@ const IconButtonWrapper = styled.div`
|
||||||
`
|
`
|
||||||
|
|
||||||
const StakeAction: React.FC<NodeCardActionsProps> = ({ stakedBalance, tokenBalance, tokenName, pid }) => {
|
const StakeAction: React.FC<NodeCardActionsProps> = ({ stakedBalance, tokenBalance, tokenName, pid }) => {
|
||||||
const TranslateString = useI18n()
|
const { t } = useTranslation()
|
||||||
const { toastWarning } = useToast()
|
const { toastWarning } = useToast()
|
||||||
const { onStake } = useNodeStake(pid)
|
const { onStake } = useStakeBoard(pid)
|
||||||
const { onUnstake } = useNodeUnstake(pid)
|
const { onUnstake } = useUnstakeBoard(pid)
|
||||||
const { tokenDecimals = 18, minStakeAmount, userData } = useBoardsFromPid(pid)
|
const { tokenDecimals = 18, minStakeAmount, userData } = useBoardsFromPid(pid)
|
||||||
const rawStakedBalance = getBalanceNumber(stakedBalance, tokenDecimals, 8)
|
const rawStakedBalance = getBalanceNumber(stakedBalance, tokenDecimals, 8)
|
||||||
const minStakedAmount = useMemo(() => {
|
const minStakedAmount = useMemo(() => {
|
||||||
|
|
@ -51,25 +52,25 @@ const StakeAction: React.FC<NodeCardActionsProps> = ({ stakedBalance, tokenBalan
|
||||||
<WithdrawModal max={stakedBalance} tokenDecimals={tokenDecimals} onConfirm={onUnstake} tokenName={tokenName} />,
|
<WithdrawModal max={stakedBalance} tokenDecimals={tokenDecimals} onConfirm={onUnstake} tokenName={tokenName} />,
|
||||||
)
|
)
|
||||||
const handleUnstake = () => {
|
const handleUnstake = () => {
|
||||||
const unstakeDay = new Date().getDay()
|
// const unstakeDay = new Date().getDay()
|
||||||
const unlockTime = userData.unlockTime * 1000
|
// const unlockTime = userData.unlockTime * 1000
|
||||||
// 只能周五解锁 NEED CHANGE
|
// // 只能周五解锁 NEED CHANGE
|
||||||
if (unstakeDay !== NODE_UNLOCK_TIME || unlockTime > new Date().getTime()) {
|
// if (unstakeDay !== NODE_UNLOCK_TIME || unlockTime > new Date().getTime()) {
|
||||||
toastWarning(
|
// toastWarning(
|
||||||
TranslateString(101012, 'Unlock time'),
|
// TranslateString(101012, 'Unlock time'),
|
||||||
`${dayjs(unlockTime).format('YYYY-MM-DD HH:mm')} Next Friday`, // NEED CHANGE
|
// `${dayjs(unlockTime).format('YYYY-MM-DD HH:mm')} Next Friday`, // NEED CHANGE
|
||||||
)
|
// )
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
if (new BigNumber(userData.stakedBalance).toJSON() !== new BigNumber(userData.xCandyBalance).toJSON()) {
|
// if (new BigNumber(userData.stakedBalance).toJSON() !== new BigNumber(userData.xCandyBalance).toJSON()) {
|
||||||
toastWarning(TranslateString(100103, 'Hint'), TranslateString(101019, 'Unlocking conditions are not met'))
|
// toastWarning(TranslateString(100103, 'Hint'), TranslateString(101019, 'Unlocking conditions are not met'))
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
onUnstake()
|
// onUnstake()
|
||||||
}
|
}
|
||||||
const renderStakingButtons = () => {
|
const renderStakingButtons = () => {
|
||||||
return rawStakedBalance === 0 ? (
|
return rawStakedBalance === 0 ? (
|
||||||
<Button onClick={onPresentDeposit}>{TranslateString(999, `Stake Token`)}</Button>
|
<Button onClick={onPresentDeposit}>{t(`Stake Token`)}</Button>
|
||||||
) : (
|
) : (
|
||||||
<IconButtonWrapper>
|
<IconButtonWrapper>
|
||||||
<IconButton variant="tertiary" onClick={handleUnstake} mr="6px">
|
<IconButton variant="tertiary" onClick={handleUnstake} mr="6px">
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
import BigNumber from 'bignumber.js'
|
import BigNumber from 'bignumber.js'
|
||||||
import React, { useCallback, useMemo, useState } from 'react'
|
import React, { useCallback, useMemo, useState } from 'react'
|
||||||
import { Button, Modal, LinkExternal } from '@pancakeswap/uikit'
|
import { Button, Modal, LinkExternal } from '@pancakeswap/uikit'
|
||||||
import ModalActions from 'components/ModalActions'
|
import { ModalActions, ModalInput } from 'components/Modal'
|
||||||
import ModalInput from 'components/ModalInput'
|
import { useTranslation } from 'contexts/Localization'
|
||||||
import useI18n from 'hooks/useI18n'
|
import useToast from 'hooks/useToast'
|
||||||
import { useToast } from 'state/hooks'
|
|
||||||
import { getFullDisplayBalance } from 'utils/formatBalance'
|
import { getFullDisplayBalance } from 'utils/formatBalance'
|
||||||
|
|
||||||
interface DepositModalProps {
|
interface DepositModalProps {
|
||||||
|
|
@ -26,10 +25,10 @@ const DepositModal: React.FC<DepositModalProps> = ({
|
||||||
tokenName = '',
|
tokenName = '',
|
||||||
addLiquidityUrl,
|
addLiquidityUrl,
|
||||||
}) => {
|
}) => {
|
||||||
const { toastWarning } = useToast()
|
const { toastSuccess, toastError, toastWarning } = useToast()
|
||||||
const [val, setVal] = useState('')
|
const [val, setVal] = useState('')
|
||||||
const [pendingTx, setPendingTx] = useState(false)
|
const [pendingTx, setPendingTx] = useState(false)
|
||||||
const TranslateString = useI18n()
|
const { t } = useTranslation()
|
||||||
const fullBalance = useMemo(() => {
|
const fullBalance = useMemo(() => {
|
||||||
return getFullDisplayBalance(max, tokenDecimals)
|
return getFullDisplayBalance(max, tokenDecimals)
|
||||||
}, [max, tokenDecimals])
|
}, [max, tokenDecimals])
|
||||||
|
|
@ -46,7 +45,7 @@ const DepositModal: React.FC<DepositModalProps> = ({
|
||||||
}, [fullBalance, setVal])
|
}, [fullBalance, setVal])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal title={TranslateString(101004, 'Stake tokens')} onDismiss={onDismiss}>
|
<Modal title={t('Stake tokens')} onDismiss={onDismiss}>
|
||||||
<ModalInput
|
<ModalInput
|
||||||
value={val}
|
value={val}
|
||||||
onSelectMax={handleSelectMax}
|
onSelectMax={handleSelectMax}
|
||||||
|
|
@ -54,34 +53,41 @@ const DepositModal: React.FC<DepositModalProps> = ({
|
||||||
max={fullBalance}
|
max={fullBalance}
|
||||||
symbol={tokenName}
|
symbol={tokenName}
|
||||||
addLiquidityUrl={addLiquidityUrl}
|
addLiquidityUrl={addLiquidityUrl}
|
||||||
inputTitle={TranslateString(101004, 'Stake')}
|
inputTitle={t('Stake')}
|
||||||
/>
|
/>
|
||||||
<ModalActions>
|
<ModalActions>
|
||||||
<Button variant="secondary" onClick={onDismiss} width="100%">
|
<Button variant="secondary" onClick={onDismiss} width="100%">
|
||||||
{TranslateString(462, 'Cancel')}
|
{t('Cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
width="100%"
|
width="100%"
|
||||||
disabled={pendingTx || fullBalance === '0' || val === '0'}
|
disabled={pendingTx || fullBalance === '0' || val === '0'}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (Number(val) < min.toNumber()) {
|
if (Number(val) < min.toNumber()) {
|
||||||
toastWarning(
|
toastWarning(t('Hint'), `${t('At least stake ')}${min.toNumber()}`)
|
||||||
TranslateString(100103, 'Hint'),
|
|
||||||
`${TranslateString(101011, 'At least stake ')}${min.toNumber()}`,
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setPendingTx(true)
|
setPendingTx(true)
|
||||||
|
try {
|
||||||
await onConfirm(val)
|
await onConfirm(val)
|
||||||
setPendingTx(false)
|
toastSuccess(t('Staked!'), t('Your funds have been staked in the farm'))
|
||||||
onDismiss()
|
onDismiss()
|
||||||
|
} catch (e) {
|
||||||
|
toastError(
|
||||||
|
t('Error'),
|
||||||
|
t('Please try again. Confirm the transaction and make sure you are paying enough gas!'),
|
||||||
|
)
|
||||||
|
console.error(e)
|
||||||
|
} finally {
|
||||||
|
setPendingTx(false)
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{pendingTx ? TranslateString(488, 'Pending Confirmation') : TranslateString(464, 'Confirm')}
|
{pendingTx ? t('Pending Confirmation') : t('Confirm')}
|
||||||
</Button>
|
</Button>
|
||||||
</ModalActions>
|
</ModalActions>
|
||||||
<LinkExternal href={addLiquidityUrl} style={{ alignSelf: 'center' }}>
|
<LinkExternal href={addLiquidityUrl} style={{ alignSelf: 'center' }}>
|
||||||
{TranslateString(100102, 'Get')} {tokenName}
|
{t('Get %symbol%', { symbol: tokenName })}
|
||||||
</LinkExternal>
|
</LinkExternal>
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import BigNumber from 'bignumber.js'
|
import BigNumber from 'bignumber.js'
|
||||||
import React, { useCallback, useMemo, useState } from 'react'
|
import React, { useCallback, useMemo, useState } from 'react'
|
||||||
import { Button, Modal } from '@pancakeswap/uikit'
|
import { Button, Modal } from '@pancakeswap/uikit'
|
||||||
import ModalActions from 'components/ModalActions'
|
import useToast from 'hooks/useToast'
|
||||||
import ModalInput from 'components/ModalInput'
|
|
||||||
import useI18n from 'hooks/useI18n'
|
import { ModalActions, ModalInput } from 'components/Modal'
|
||||||
|
import { useTranslation } from 'contexts/Localization'
|
||||||
import { getFullDisplayBalance } from 'utils/formatBalance'
|
import { getFullDisplayBalance } from 'utils/formatBalance'
|
||||||
|
|
||||||
interface WithdrawModalProps {
|
interface WithdrawModalProps {
|
||||||
|
|
@ -23,11 +24,14 @@ const WithdrawModal: React.FC<WithdrawModalProps> = ({
|
||||||
}) => {
|
}) => {
|
||||||
const [val, setVal] = useState('')
|
const [val, setVal] = useState('')
|
||||||
const [pendingTx, setPendingTx] = useState(false)
|
const [pendingTx, setPendingTx] = useState(false)
|
||||||
const TranslateString = useI18n()
|
const { t } = useTranslation()
|
||||||
const fullBalance = useMemo(() => {
|
const fullBalance = useMemo(() => {
|
||||||
return getFullDisplayBalance(max, tokenDecimals)
|
return getFullDisplayBalance(max)
|
||||||
}, [max, tokenDecimals])
|
}, [max])
|
||||||
|
const { toastSuccess, toastError } = useToast()
|
||||||
|
|
||||||
|
const valNumber = new BigNumber(val)
|
||||||
|
const fullBalanceNumber = new BigNumber(fullBalance)
|
||||||
const handleChange = useCallback(
|
const handleChange = useCallback(
|
||||||
(e: React.FormEvent<HTMLInputElement>) => {
|
(e: React.FormEvent<HTMLInputElement>) => {
|
||||||
setVal(e.currentTarget.value)
|
setVal(e.currentTarget.value)
|
||||||
|
|
@ -40,30 +44,40 @@ const WithdrawModal: React.FC<WithdrawModalProps> = ({
|
||||||
}, [fullBalance, setVal])
|
}, [fullBalance, setVal])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal title={TranslateString(101008, 'Unstake tokens')} onDismiss={onDismiss}>
|
<Modal title={t('Unstake LP tokens')} onDismiss={onDismiss}>
|
||||||
<ModalInput
|
<ModalInput
|
||||||
onSelectMax={handleSelectMax}
|
onSelectMax={handleSelectMax}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
value={val}
|
value={val}
|
||||||
max={fullBalance}
|
max={fullBalance}
|
||||||
symbol={tokenName}
|
symbol={tokenName}
|
||||||
inputTitle={TranslateString(588, 'Unstake')}
|
inputTitle={t('Unstake')}
|
||||||
/>
|
/>
|
||||||
<ModalActions>
|
<ModalActions>
|
||||||
<Button variant="secondary" onClick={onDismiss} width="100%">
|
<Button variant="secondary" onClick={onDismiss} width="100%" disabled={pendingTx}>
|
||||||
{TranslateString(462, 'Cancel')}
|
{t('Cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
disabled={pendingTx}
|
disabled={pendingTx || !valNumber.isFinite() || valNumber.eq(0) || valNumber.gt(fullBalanceNumber)}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
setPendingTx(true)
|
setPendingTx(true)
|
||||||
|
try {
|
||||||
await onConfirm(val)
|
await onConfirm(val)
|
||||||
setPendingTx(false)
|
toastSuccess(t('Unstaked!'), t('Your earnings have also been harvested to your wallet'))
|
||||||
onDismiss()
|
onDismiss()
|
||||||
|
} catch (e) {
|
||||||
|
toastError(
|
||||||
|
t('Error'),
|
||||||
|
t('Please try again. Confirm the transaction and make sure you are paying enough gas!'),
|
||||||
|
)
|
||||||
|
console.error(e)
|
||||||
|
} finally {
|
||||||
|
setPendingTx(false)
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
width="100%"
|
width="100%"
|
||||||
>
|
>
|
||||||
{pendingTx ? TranslateString(488, 'Pending Confirmation') : TranslateString(464, 'Confirm')}
|
{pendingTx ? t('Pending Confirmation') : t('Confirm')}
|
||||||
</Button>
|
</Button>
|
||||||
</ModalActions>
|
</ModalActions>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { useCallback } from 'react'
|
||||||
|
import { ethers, Contract } from 'ethers'
|
||||||
|
import { useBoardchef } from 'hooks/useContract'
|
||||||
|
|
||||||
|
const useApproveBoard = (lpContract: Contract) => {
|
||||||
|
const boardChefContract = useBoardchef()
|
||||||
|
const handleApprove = useCallback(async () => {
|
||||||
|
try {
|
||||||
|
const tx = await lpContract.approve(boardChefContract.address, ethers.constants.MaxUint256)
|
||||||
|
const receipt = await tx.wait()
|
||||||
|
return receipt.status
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}, [lpContract, boardChefContract])
|
||||||
|
|
||||||
|
return { onApprove: handleApprove }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useApproveBoard
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { useCallback } from 'react'
|
||||||
|
import { harvestFarm } from 'utils/calls'
|
||||||
|
import { useBoardchef } from 'hooks/useContract'
|
||||||
|
|
||||||
|
const useHarvestBoard = (boardPid: number) => {
|
||||||
|
const boardChefContract = useBoardchef()
|
||||||
|
|
||||||
|
const handleHarvest = useCallback(async () => {
|
||||||
|
await harvestFarm(boardChefContract, boardPid)
|
||||||
|
}, [boardPid, boardChefContract])
|
||||||
|
|
||||||
|
return { onReward: handleHarvest }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useHarvestBoard
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
export const useNodeStake = (pid: number) => {
|
import { useCallback } from 'react'
|
||||||
const dispatch = useDispatch()
|
import { stakeFarm } from 'utils/calls'
|
||||||
const { account } = useWeb3React()
|
import { useBoardchef } from 'hooks/useContract'
|
||||||
const nodeChefContract = useNodechef()
|
|
||||||
const { tokenDecimals = 18 } = useNodesFromPid(pid)
|
const useStakeBoard = (pid: number) => {
|
||||||
|
const boardChefContract = useBoardchef()
|
||||||
|
|
||||||
const handleStake = useCallback(
|
const handleStake = useCallback(
|
||||||
async (amount: string) => {
|
async (amount: string) => {
|
||||||
const txHash = await nodeStake(nodeChefContract, amount, account, tokenDecimals)
|
const txHash = await stakeFarm(boardChefContract, pid, amount)
|
||||||
// dispatch(fetchFarmsPublicDataAsync())
|
|
||||||
// dispatch(fetchFarmUserDataAsync(account))
|
|
||||||
console.info(txHash)
|
console.info(txHash)
|
||||||
},
|
},
|
||||||
[account, dispatch, nodeChefContract, tokenDecimals],
|
[boardChefContract, pid],
|
||||||
)
|
)
|
||||||
|
|
||||||
return { onStake: handleStake }
|
return { onStake: handleStake }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useNodeStake
|
export default useStakeBoard
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { useCallback } from 'react'
|
||||||
|
import { unstakeFarm } from 'utils/calls'
|
||||||
|
import { useBoardchef } from 'hooks/useContract'
|
||||||
|
|
||||||
|
const useUnstakeBoard = (pid: number) => {
|
||||||
|
const boardChefContract = useBoardchef()
|
||||||
|
|
||||||
|
const handleUnstake = useCallback(
|
||||||
|
async (amount: string) => {
|
||||||
|
await unstakeFarm(boardChefContract, pid, amount)
|
||||||
|
},
|
||||||
|
[boardChefContract, pid],
|
||||||
|
)
|
||||||
|
|
||||||
|
return { onUnstake: handleUnstake }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useUnstakeBoard
|
||||||
|
|
@ -10,7 +10,7 @@ import Page from 'components/Layout/Page'
|
||||||
import { useBoards } from 'state/hooks'
|
import { useBoards } from 'state/hooks'
|
||||||
import useRefresh from 'hooks/useRefresh'
|
import useRefresh from 'hooks/useRefresh'
|
||||||
import { fetchBoardUserDataAsync, fetchBoardsPublicDataAsync } from 'state/actions'
|
import { fetchBoardUserDataAsync, fetchBoardsPublicDataAsync } from 'state/actions'
|
||||||
import useI18n from 'hooks/useI18n'
|
import { useTranslation } from 'contexts/Localization'
|
||||||
import BoardCard from './components/BoardCard/BoardCard'
|
import BoardCard from './components/BoardCard/BoardCard'
|
||||||
|
|
||||||
const Header = styled.div`
|
const Header = styled.div`
|
||||||
|
|
@ -28,7 +28,7 @@ const SecondText = styled(Text)`
|
||||||
white-space: break-spaces;
|
white-space: break-spaces;
|
||||||
`
|
`
|
||||||
const Farms: React.FC = () => {
|
const Farms: React.FC = () => {
|
||||||
const TranslateString = useI18n()
|
const { t } = useTranslation()
|
||||||
const boardsList = useBoards()
|
const boardsList = useBoards()
|
||||||
const [query, setQuery] = useState('')
|
const [query, setQuery] = useState('')
|
||||||
const { account } = useWeb3React()
|
const { account } = useWeb3React()
|
||||||
|
|
@ -63,11 +63,10 @@ const Farms: React.FC = () => {
|
||||||
<>
|
<>
|
||||||
<Header>
|
<Header>
|
||||||
<Heading as="h1" size="xl" color="text" mb="10px" mt="10px">
|
<Heading as="h1" size="xl" color="text" mb="10px" mt="10px">
|
||||||
{TranslateString(100004, 'Boards')}
|
{t('Boards')}
|
||||||
</Heading>
|
</Heading>
|
||||||
<SecondText fontSize="28px" color="text">
|
<SecondText fontSize="28px" color="text">
|
||||||
{TranslateString(
|
{t(
|
||||||
101013,
|
|
||||||
'Joining the board of directors will obtain the governance token xcandy \n participate in the governance of the project, vote, obtain additional pledge income, \n and have a higher invitation airdrop reward',
|
'Joining the board of directors will obtain the governance token xcandy \n participate in the governance of the project, vote, obtain additional pledge income, \n and have a higher invitation airdrop reward',
|
||||||
)}
|
)}
|
||||||
</SecondText>
|
</SecondText>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue