-
Notifications
You must be signed in to change notification settings - Fork 54
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
Rewards/MyRewards: add etherscan link #1653
base: dev
Are you sure you want to change the base?
Changes from all commits
ca4f5e2
babfc38
66d77c8
3ab3915
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,12 @@ | ||
import PropTypes from 'prop-types' | ||
import React from 'react' | ||
import React, { useState } from 'react' | ||
import styled from 'styled-components' | ||
import { | ||
ContextMenu, | ||
ContextMenuItem, | ||
DataView, | ||
IconCoin, | ||
IconHash, | ||
IconView, | ||
Text, | ||
useTheme, | ||
|
@@ -14,48 +15,62 @@ import { | |
ONE_TIME_DIVIDEND, | ||
RECURRING_DIVIDEND, | ||
ONE_TIME_MERIT, | ||
READY, | ||
CLAIMED, | ||
} from '../../utils/constants' | ||
import { Empty } from '../Card' | ||
import Metrics from './Metrics' | ||
import { useAppState } from '@aragon/api-react' | ||
import { useAppState, useAragonApi, useNetwork } from '@aragon/api-react' | ||
import BigNumber from 'bignumber.js' | ||
import { displayCurrency, getStatus } from '../../utils/helpers' | ||
import { displayCurrency, getStatus, getStatusId } from '../../utils/helpers' | ||
|
||
const MyRewards = ({ | ||
myRewards, | ||
myMetrics, | ||
viewReward, | ||
claimReward, | ||
claimHashes, | ||
}) => { | ||
const network = useNetwork() | ||
const rewardsEmpty = myRewards.length === 0 | ||
const { api } = useAragonApi() | ||
const [ user, setUser ] = useState() | ||
api.accounts().subscribe(accounts => setUser(accounts[0])) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this the same as Why include the user's address in the const link = `https://${networkChunk}etherscan.io/tx/${reward.transactionHash}` There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because of the way rewards work. You create a reward, and then any token holder can claim it. Since multiple users should be able to claim a reward at any time, we need to track who claimed it. Your approach would only store the last claim, so every user would see the last claim made by any user, instead of their own claim. |
||
|
||
const getEtherscanLink = reward => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this use any component state? If not, let's move it outside the definition of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer we use const getEtherescanLink = useCallback(reward => {
// existing function here
}, [ claimHashes, network ]) Benefits:
|
||
const networkChunk = network.id === 1 ? '' : `${network.type}.` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could have used There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you test this and check? Does it use the user-configured setting from MetaMask? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What I meant by this not having been tested is that it can only be tested on mainnet. Or am I missing something? What setting from Metamask? If you're wondering about the network id, there's no doubt that mainnet is 1. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess I'm wondering if How does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's just an interface that gets an updated value for the Aragon's api It gets the value from the current provider, it can be MM or other tool injecting the provider. The answer is yes it responds to the user setting in MetaMask |
||
const claimHash = claimHashes[reward.rewardId][user] | ||
const link = `https://${networkChunk}etherscan.io/tx/${claimHash}` | ||
return link | ||
e18r marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
if (rewardsEmpty) { | ||
return <Empty noButton /> | ||
} | ||
|
||
const renderMenu = (reward) => ( | ||
<ContextMenu> | ||
<StyledContextMenuItem | ||
onClick={() => viewReward(reward)} | ||
> | ||
<IconView css={{ | ||
marginRight: '11px', | ||
marginBottom: '2px', | ||
}}/> | ||
View | ||
</StyledContextMenuItem> | ||
{(reward.claims < reward.disbursements.length && (reward.disbursements[reward.claims] < Date.now())) && ( | ||
<StyledContextMenuItem | ||
onClick={() => claimReward(reward)} | ||
> | ||
<IconCoin css={{ | ||
marginRight: '11px', | ||
marginBottom: '2px', | ||
}}/> | ||
Claim | ||
</StyledContextMenuItem>)} | ||
</ContextMenu> | ||
) | ||
const renderMenu = (reward) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could also move this outside of the component, and make it a component. But that's probably out-of-scope for now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So Does it still make sense for it to become a functional component and/or be moved outside? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still think it makes sense to move it outside. I guess we can't make it a component right now, though it might be worth opening an issue in the aragonUI repo. |
||
const statusId = getStatusId(reward) | ||
return ( | ||
<ContextMenu> | ||
<StyledContextMenuItem onClick={() => viewReward(reward)} > | ||
<StyledIcon Icon={IconView} /> | ||
View reward | ||
</StyledContextMenuItem> | ||
{statusId === READY && ( | ||
<StyledContextMenuItem onClick={() => claimReward(reward)} > | ||
<StyledIcon Icon={IconCoin} /> | ||
Claim | ||
</StyledContextMenuItem> | ||
)} | ||
{statusId === CLAIMED && ( | ||
<StyledContextMenuItem href={getEtherscanLink(reward)}> | ||
<StyledIcon Icon={IconHash} /> | ||
View on Etherscan | ||
</StyledContextMenuItem> | ||
)} | ||
</ContextMenu> | ||
) | ||
} | ||
|
||
return ( | ||
<OverviewMain> | ||
|
@@ -143,6 +158,13 @@ MyRewards.propTypes = { | |
myMetrics: PropTypes.arrayOf(PropTypes.object).isRequired, | ||
} | ||
|
||
const StyledIcon = ({ Icon }) => ( | ||
<Icon style={{ | ||
marginRight: '11px', | ||
marginBottom: '2px', | ||
}}/> | ||
) | ||
|
||
const OverviewMain = styled.div` | ||
background-color: #f8fcfd; | ||
` | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,12 @@ import { addressesEqual } from '../utils/web3-utils' | |
import { INITIALIZATION_TRIGGER } from './' | ||
|
||
export const handleEvent = async (state, event, settings) => { | ||
const { event: eventName, returnValues, address: eventAddress, } = event | ||
const { | ||
event: eventName, | ||
returnValues, | ||
address: eventAddress, | ||
transactionHash, | ||
} = event | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we access the network here, rather than in the frontend? We don't want the link to change, depending on which network the user is currently connected to. We want to link them to the URL where they can view the actual transaction, whichever network that happened to be on! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you're on one network you won't see any rewards made on another network in the first place, so I think it's safe to access the network from the frontend. |
||
const { vault } = settings | ||
|
||
let nextState = { ...state, } | ||
|
@@ -25,7 +30,11 @@ export const handleEvent = async (state, event, settings) => { | |
nextState.isSyncing = false | ||
break | ||
case 'RewardClaimed': | ||
nextState = await onRewardClaimed(nextState, returnValues) | ||
nextState = await onRewardClaimed( | ||
nextState, | ||
returnValues, | ||
transactionHash | ||
) | ||
break | ||
case 'RewardAdded': | ||
nextState = await onRewardAdded(nextState, returnValues, settings) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can I remove the
useAppState
hook and importappState
fromuseAragonApi
? I've seen it elsewhere but I'm not 100% sure it's the same thing.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes 😄
They are the same, and I think I prefer always using
useAragonApi