Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround while subgraph is not yet synced to show users their linke… #115

Merged
merged 3 commits into from
Jan 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion tinlake-ui/components/WalletRewards/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ export const WalletRewards = ({ address }: { address: string }) => {
RAD
</Number>
</Box>
<Button secondary onClick={() => router.push('/rewards')} label="Claim RAD" margin={{ left: 'auto' }} />
{router.route !== '/rewards' && (
<Button secondary onClick={() => router.push('/rewards')} label="Claim RAD" margin={{ left: 'auto' }} />
)}
</Cont>
)
}
Expand Down
30 changes: 27 additions & 3 deletions tinlake-ui/containers/ClaimRewards/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Tooltip } from '@centrifuge/axis-tooltip'
import { baseToDisplay } from '@centrifuge/tinlake-js'
import BN from 'bn.js'
import { Anchor, Box, Button } from 'grommet'
import { useRouter } from 'next/router'
import * as React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import styled from 'styled-components'
Expand Down Expand Up @@ -54,6 +55,10 @@ const ClaimRewards: React.FC<Props> = ({ activeLink }: Props) => {
}
}

const {
query: { allowClaim },
} = useRouter()

if (activeLink.claimable === null || activeLink.claimed === null || claims === null) {
return <Box pad="medium">Loading claimable rewards...</Box>
}
Expand All @@ -67,8 +72,25 @@ const ClaimRewards: React.FC<Props> = ({ activeLink }: Props) => {
{unclaimed && !unclaimed?.isZero() ? (
(status === null || status === 'unconfirmed' || status === 'failed' || status === 'pending') && (
<>
🎉 You can claim {addThousandsSeparators(toDynamicPrecision(baseToDisplay(unclaimed, 18)))} RAD rewards.
Claim now to stake RAD and participate in on-chain governance.
🎉 You can claim {addThousandsSeparators(toDynamicPrecision(baseToDisplay(unclaimed, 18)))} RAD rewards.{' '}
{/* TODO remove this, just temporary. */}
{allowClaim ? (
'Claim now to stake RAD and participate in on-chain governance.'
) : (
<>
<br />
<br />
It will take a few hours until you can claim your rewards. Please come back tomorrow.
<br />
<br />
<Tooltip
title="Why do I have to wait?"
description={`Communication between the Ethereum blockchain and our Centrifuge Chain is semi-automated. Earned rewards will be observed by a relayer, a proof will be generated, and that proof will be committed on Centrfiuge Chain. This process is triggered manually right now. We are working to speed this up to a delay of a maximum of minutes.`}
>
<Small>Why do I have to wait?</Small>
</Tooltip>
</>
)}
{claimExtHash && (
<>
<br />
Expand Down Expand Up @@ -158,7 +180,9 @@ const ClaimRewards: React.FC<Props> = ({ activeLink }: Props) => {
<Button
margin={{ left: 'auto' }}
label={status === 'unconfirmed' || status === 'pending' ? `Claiming...` : `Claim`}
disabled={(!!unclaimed && unclaimed.isZero()) || status === 'unconfirmed' || status === 'pending'}
disabled={
!allowClaim || (!!unclaimed && unclaimed.isZero()) || status === 'unconfirmed' || status === 'pending'
}
onClick={claim}
/>
</RewardStripe>
Expand Down
48 changes: 34 additions & 14 deletions tinlake-ui/containers/SetCentAccount/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import styled from 'styled-components'
import { AuthState } from '../../ducks/auth'
import { CentChainWalletState, InjectedAccount } from '../../ducks/centChainWallet'
import { createTransaction, TransactionProps, useTransactionState } from '../../ducks/transactions'
import { loadSubgraph } from '../../ducks/userRewards'
import { loadEthLink, loadSubgraph, UserRewardsState } from '../../ducks/userRewards'
import { accountIdToCentChainAddr } from '../../services/centChain/accountIdToCentChainAddr'
import { centChainAddrToAccountId } from '../../services/centChain/centChainAddrToAccountId'
import { isCentChainAddr } from '../../services/centChain/isCentChainAddr'
import { shortAddr } from '../../utils/shortAddr'
Expand All @@ -19,6 +20,7 @@ interface Props extends TransactionProps {
let interval: number | null = null

const SetCentAccount: React.FC<Props> = ({ createTransaction, tinlake }: Props) => {
const userRewards = useSelector<any, UserRewardsState>((state: any) => state.userRewards)
const cWallet = useSelector<any, CentChainWalletState>((state: any) => state.centChainWallet)
const { address: ethAddr } = useSelector<any, AuthState>((state: any) => state.auth)
const [selectedCentAcc, selectCentAcc] = React.useState<InjectedAccount>()
Expand Down Expand Up @@ -50,6 +52,7 @@ const SetCentAccount: React.FC<Props> = ({ createTransaction, tinlake }: Props)
}

// poll changes
dispatch(loadEthLink(ethAddr, tinlake))
dispatch(loadSubgraph(ethAddr))
if (!interval) {
interval = setInterval(async () => {
Expand All @@ -59,33 +62,50 @@ const SetCentAccount: React.FC<Props> = ({ createTransaction, tinlake }: Props)
}
}, [status, ethAddr])

React.useEffect(
() => () => {
React.useEffect(() => {
if (ethAddr) {
dispatch(loadEthLink(ethAddr, tinlake))
}

return function cleanup() {
if (interval) {
clearInterval(interval)
interval = null
}
},
[ethAddr]
)
}
}, [ethAddr])

const disabled =
status === 'unconfirmed' ||
status === 'pending' ||
!selectedCentAcc ||
!isCentChainAddr(selectedCentAcc.addrCentChain)
if (userRewards.ethLinkState !== 'found') {
return null
}

if (status === 'succeeded') {
if (userRewards.ethLinkState === 'found' && userRewards.ethLink) {
return (
<div>
Your Centrifuge Chain account has been successfully linked to your Ethereum account.
Your Centrifuge Chain account {accountIdToCentChainAddr(userRewards.ethLink)} has been successfully linked to
your Ethereum account.
<br />
<br />
It will take a few hours for that information to load. Please come back tomorrow.
{/* TODO replace with: It may take a few minutes for that information to load. This page will automatically refresh once done. */}
<br />
<br />
It may take a few minutes for that information to load. This page will automatically refresh once done.
<Tooltip
title="Why so slow?"
description={`Communication between the Ethereum blockchain and our Centrifuge Chain is semi-automated. Every link transaction on Ethereum will be observed by a relayer, a proof will be generated, and that proof will be committed on Centrfiuge Chain. This process is triggered manually right now. We are working to speed this up to a delay of a maximum of minutes.`}
>
<Small>Why so slow?</Small>
</Tooltip>
</div>
)
}

const disabled =
status === 'unconfirmed' ||
status === 'pending' ||
!selectedCentAcc ||
!isCentChainAddr(selectedCentAcc.addrCentChain)

return (
<div>
Select the Centrifuge Chain account you want to link to your Ethereum account below.{' '}
Expand Down
2 changes: 1 addition & 1 deletion tinlake-ui/containers/UserRewards/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import styled from 'styled-components'
import Alert from '../../components/Alert'
import { LoadingValue } from '../../components/LoadingValue'
import NumberDisplay from '../../components/NumberDisplay'
import { Cont, Label, TokenLogo, Unit, Value } from '../../components/PoolsMetrics/styles'
import PageTitle from '../../components/PageTitle'
import { Cont, Label, TokenLogo, Unit, Value } from '../../components/PoolsMetrics/styles'
import { AuthState, ensureAuthed } from '../../ducks/auth'
import { CentChainWalletState } from '../../ducks/centChainWallet'
import { maybeLoadRewards, RewardsState } from '../../ducks/rewards'
Expand Down
25 changes: 25 additions & 0 deletions tinlake-ui/ducks/userRewards.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ITinlake } from '@centrifuge/tinlake-js'
import BN from 'bn.js'
import { HYDRATE } from 'next-redux-wrapper'
import { Action, AnyAction } from 'redux'
Expand All @@ -9,6 +10,8 @@ import { centChainService } from '../services/centChain'
// Actions
const LOAD_SUBGRAPH = 'tinlake-ui/user-rewards/LOAD_SUBGRAPH'
const RECEIVE_SUBGRAPH = 'tinlake-ui/user-rewards/RECEIVE_SUBGRAPH'
const LOAD_ETH_LINK = 'tinlake-ui/user-rewards/LOAD_ETH_LINK'
const RECEIVE_ETH_LINK = 'tinlake-ui/user-rewards/RECEIVE_ETH_LINK'
const LOAD_CENT_CHAIN = 'tinlake-ui/user-rewards/LOAD_CENT_CHAIN'
const RECEIVE_CENT_CHAIN = 'tinlake-ui/user-rewards/RECEIVE_CENT_CHAIN'
const LOAD_CLAIMS = 'tinlake-ui/user-rewards/LOAD_CLAIMS'
Expand All @@ -23,6 +26,8 @@ export interface UserRewardsState {
data: null | UserRewardsData
claimsState: null | 'loading' | 'found'
claims: null | RewardClaim[]
ethLinkState: null | 'loading' | 'found'
ethLink: null | string
}

/**
Expand Down Expand Up @@ -113,6 +118,8 @@ const initialState: UserRewardsState = {
data: null,
claimsState: null,
claims: null,
ethLinkState: null,
ethLink: null,
}

export default function reducer(
Expand Down Expand Up @@ -155,6 +162,10 @@ export default function reducer(
: null,
}
}
case LOAD_ETH_LINK:
return { ...state, ethLink: null, ethLinkState: 'loading' }
case RECEIVE_ETH_LINK:
return { ...state, ethLink: action.link, ethLinkState: 'found' }
default:
return state
}
Expand All @@ -180,6 +191,20 @@ export function loadSubgraph(
}
}

export function loadEthLink(
ethAddr: string,
tinlake: ITinlake
): ThunkAction<Promise<void>, { userRewards: UserRewardsState }, undefined, Action> {
return async (dispatch) => {
dispatch({ type: LOAD_ETH_LINK, ethAddr })
let link: null | string = await tinlake.getClaimRADAccountID(ethAddr)
if (link === '0x0000000000000000000000000000000000000000000000000000000000000000') {
link = null
}
dispatch({ type: RECEIVE_ETH_LINK, link })
}
}

export function loadCentChain(): ThunkAction<Promise<void>, { userRewards: UserRewardsState }, undefined, Action> {
return async (dispatch, getState) => {
const { userRewards } = getState()
Expand Down