Skip to content

Commit

Permalink
Display snapshot and POAP + ENS support (#411)
Browse files Browse the repository at this point in the history
* Add snapshot activity

* Add getDateFromUnix

* Tidy up profile page

* Add support for POAP badges

* Show Snapshot avatar and fix TwitterAvatar

* Display spaces on event page

* Add alt title

* Display ENS reverse record

* Support ENS forward lookup

* Change prefix
  • Loading branch information
makoto authored Jun 2, 2021
1 parent 58013e4 commit 64d1543
Show file tree
Hide file tree
Showing 12 changed files with 384 additions and 72 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"dependencies": {
"@emotion/core": "^10.0.27",
"@emotion/styled": "^10.0.27",
"@ensdomains/ens-contracts": "^0.0.3",
"@wearekickback/contracts": "npm:@wearekickback/[email protected]",
"@wearekickback/shared": "^1.14.1",
"apollo-cache-inmemory": "^1.2.8",
Expand Down
44 changes: 43 additions & 1 deletion src/api/rootResolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import getWeb3, {
getAccount,
getEvents,
getDeployerAddress,
isLocalEndpoint
isLocalEndpoint,
getWeb3ForNetwork
} from './web3'
import singleEventResolvers, {
defaults as singleEventDefaults
Expand All @@ -16,6 +17,24 @@ import tokenResolvers, {
defaults as tokenDefaults
} from './resolvers/tokenResolvers'

let reverseAddress = '0x3671aE578E63FdF66ad4F3E12CC0c0d71Ac7510C'
let reverseAbi = [
{
inputs: [{ internalType: 'contract ENS', name: '_ens', type: 'address' }],
stateMutability: 'nonpayable',
type: 'constructor'
},
{
inputs: [
{ internalType: 'address[]', name: 'addresses', type: 'address[]' }
],
name: 'getNames',
outputs: [{ internalType: 'string[]', name: 'r', type: 'string[]' }],
stateMutability: 'view',
type: 'function'
}
]

const deployerAbi = Deployer.abi

const rootDefaults = {
Expand Down Expand Up @@ -55,6 +74,29 @@ const resolvers = {
address: event.args.deployedAddress,
__typename: event.event
}))
},
async poapBadges(_, { userAddress }) {
let response = await fetch(
`https://api.poap.xyz/actions/scan/${userAddress}`
)
return response.json()
},
async getEnsName(_, { userAddress }) {
const web3 = await getWeb3ForNetwork('1')
const contract = new web3.eth.Contract(reverseAbi, reverseAddress).methods

const name = await contract.getNames([userAddress]).call()
return {
name
}
},
async getEnsAddress(_, { name }) {
const web3 = await getWeb3ForNetwork('1')
const address = await web3.eth.ens.getAddress(name)

return {
address
}
}
},

Expand Down
5 changes: 2 additions & 3 deletions src/components/Header/WalletButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { GlobalConsumer } from '../../GlobalState'
import Button from '../Forms/Button'
import UserProfileButton from './UserProfileButton'
import EtherScanLink from '../Links/EtherScanLink'
import AddressLink from '../Links/AddressLink'
import c from '../../colours'

const WalletWrapper = styled('div')`
Expand Down Expand Up @@ -78,9 +79,7 @@ function WalletButton() {
<List>
{userAddress && (
<ListItem>
<EtherScanLink address={userAddress}>
{userAddress.slice(0, 6)}...{userAddress.slice(-4)}
</EtherScanLink>
<AddressLink userAddress={userAddress} />
</ListItem>
)}
{loggedIn && userProfile && (
Expand Down
27 changes: 27 additions & 0 deletions src/components/Links/AddressLink.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react'
import styled from '@emotion/styled'
import { ENS_NAME_QUERY } from '../../graphql/queries'
import { useQuery } from 'react-apollo'
import EtherScanLink from '../Links/EtherScanLink'

const AddressLink = ({ userAddress, prefix = '' }) => {
const { data: ensData } = useQuery(ENS_NAME_QUERY, {
variables: { userAddress }
})

const ensName =
ensData &&
ensData.getEnsName &&
ensData.getEnsName.name &&
ensData.getEnsName.name[0]

return (
<EtherScanLink address={userAddress}>
{ensName
? `${prefix}${ensName}`
: `${prefix}${userAddress.slice(0, 6)}...${userAddress.slice(-4)}`}
</EtherScanLink>
)
}

export default AddressLink
70 changes: 60 additions & 10 deletions src/components/SingleEvent/EventParticipants.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,22 @@ import DefaultEventFilters from './EventFilters'

import { H3 } from '../Typography/Basic'
import { sortParticipants, filterParticipants } from '../../utils/parties'
import { GET_CONTRIBUTIONS_BY_PARTY } from '../../graphql/queries'
import {
GET_CONTRIBUTIONS_BY_PARTY,
SNAPSHOT_VOTES_SUBGRAPH_QUERY
} from '../../graphql/queries'
import SafeQuery from '../SafeQuery'
import { useQuery } from 'react-apollo'
import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { HttpLink } from 'apollo-link-http'
import _ from 'lodash'

const cache = new InMemoryCache()
const link = new HttpLink({
uri: 'https://hub.snapshot.page/graphql'
})
const graphClient = new ApolloClient({ cache, link })

const EventParticipantsContainer = styled('div')`
display: grid;
Expand Down Expand Up @@ -53,6 +67,10 @@ const EventParticipants = props => {
const handleSearch = search => {
setSearch((search || '').toLowerCase())
}
const { data: snapshotData } = useQuery(SNAPSHOT_VOTES_SUBGRAPH_QUERY, {
variables: { userAddresses: participants.map(p => p.user.address) },
client: graphClient
})

return (
<SafeQuery
Expand All @@ -78,15 +96,47 @@ const EventParticipants = props => {
participants
.sort(sortParticipants)
.filter(filterParticipants(selectedFilter, search))
.map(participant => (
<Participant
amAdmin={amAdmin}
participant={participant}
contributions={data && data.getContributionsByParty}
party={party}
key={`${participant.address}${participant.index}`}
/>
))
.map(participant => {
let votes =
snapshotData &&
snapshotData.votes
.filter(v => {
return (
v.voter.toLowerCase() ==
participant.user.address.toLowerCase()
)
})
.map(v => {
return {
id: v.space.id,
avatar: v.space.avatar,
created: v.created
}
})
let spaces = {}
votes &&
votes.map(v => {
if (!spaces[v.id] || v.created > spaces[v.id].created) {
spaces[v.id] = v
}
})
let filteredSpaces = _.sortBy(Object.values(spaces), [
function(o) {
return o.created
}
]).reverse()

return (
<Participant
amAdmin={amAdmin}
participant={participant}
contributions={data && data.getContributionsByParty}
spaces={filteredSpaces.slice(0, 5)}
party={party}
key={`${participant.address}${participant.index}`}
/>
)
})
) : (
<NoParticipants>No one is attending.</NoParticipants>
)}
Expand Down
25 changes: 24 additions & 1 deletion src/components/SingleEvent/Participant.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,29 @@ const TwitterAvatar = styled(DefaultTwitterAvatar)`
margin-bottom: 5px;
`

function Participant({ participant, party, amAdmin, decimals, contributions }) {
const OrgAvatarImg = styled(`img`)`
width: 15px;
margin: 2px, 5px;
`

const OrgAvatars = function({ spaces }) {
return (
<div>
{spaces.map(s => (
<OrgAvatarImg src={s.avatar} alt={s.id} title={s.id}></OrgAvatarImg>
))}
</div>
)
}

function Participant({
participant,
party,
amAdmin,
decimals,
contributions,
spaces
}) {
const { user, status } = participant
const { deposit, ended } = party

Expand All @@ -80,6 +102,7 @@ function Participant({ participant, party, amAdmin, decimals, contributions }) {
<ParticipantId>
<ParticipantUsername>{user.username}</ParticipantUsername>
</ParticipantId>
<OrgAvatars spaces={spaces} />
{ended ? (
attended ? (
contribution ? (
Expand Down
6 changes: 6 additions & 0 deletions src/components/Typography/Basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ export const H3 = styled('h3')`
margin-top: 0;
`

export const H4 = styled('h4')`
font-size: 16px;
font-family: Muli;
margin-top: 0;
`

export const P = styled('p')`
font-family: Muli;
font-weight: 400;
Expand Down
Loading

0 comments on commit 64d1543

Please sign in to comment.