Use directory contract (#105)

This commit is contained in:
Szymon Szlachtowicz 2021-07-13 12:18:44 +02:00 committed by GitHub
parent d1fd8e04a5
commit 01710ff198
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 180 additions and 76 deletions

View File

@ -4,16 +4,14 @@ import { CardCommunity } from '../card/CardCommunity'
import { CardFeature } from '../card/CardFeature'
import styled from 'styled-components'
import { CommunityDetail, DirectorySortingEnum } from '../../models/community'
import { useCommunities } from '../../hooks/useCommunities'
import { getCommunitiesInDirectory } from '../../helpers/apiMock'
import { FilterList } from '../Filter'
import { Search } from '../Input'
import { PageBar } from '../PageBar'
import { DirectorySortingOptions } from '../../constants/SortingOptions'
import { useConfig } from '../../providers/config'
import { Colors } from '../../constants/styles'
import { WeeklyFeature } from '../WeeklyFeature'
import { DirectoryCardSkeleton } from './DirectoryCardSkeleton'
import { useDirectoryCommunities } from '../../hooks/useDirectoryCommunities'
import { useContracts } from '../../hooks/useContracts'
import { useContractCall } from '@usedapp/core'
import { votingFromRoom } from '../../helpers/voting'
@ -70,14 +68,9 @@ function DirectoryCard({ community }: DirectoryCardProps) {
}
export function DirectoryCards() {
const { config } = useConfig()
const [filterKeyword, setFilterKeyword] = useState('')
const [sortedBy, setSortedBy] = useState(DirectorySortingEnum.IncludedRecently)
const { communities, loading } = useCommunities(getCommunitiesInDirectory, {
numberPerPage: config.numberPerPage,
sortedBy,
filterKeyword,
})
const communities = useDirectoryCommunities(filterKeyword, sortedBy)
return (
<>
@ -95,14 +88,8 @@ export function DirectoryCards() {
{communities.map((community) => (
<DirectoryCard key={community.publicKey} community={community} />
))}
{communities.length === 0 && <DirectoryCardSkeleton />}
</Voting>
{loading && (
<>
<DirectoryCardSkeleton />
<DirectoryCardSkeleton />
<DirectoryCardSkeleton />
</>
)}
</>
)
}

View File

@ -0,0 +1,85 @@
import { CommunityDetail, DirectorySortingEnum, VotingSortingEnum } from '../models/community'
import { DetailedVotingRoom } from '../models/smartContract'
export function isTextInDetails(filterKeyword: string, details: any) {
return (
details.name.toLowerCase().includes(filterKeyword.toLowerCase()) ||
details.description.toLowerCase().includes(filterKeyword.toLowerCase()) ||
details.tags.findIndex((item: any) => filterKeyword.toLowerCase() === item.toLowerCase()) > -1
)
}
export function isTypeInRoom(voteType: string, room: any) {
if (!voteType) {
return true
}
if (voteType === 'Add') {
return room.voteType === 1
}
if (voteType === 'Remove') {
return room.voteType === 0
}
return false
}
export function sortVotingFunction(sortedBy: VotingSortingEnum) {
switch (sortedBy) {
case VotingSortingEnum.AtoZ:
return (a: DetailedVotingRoom, b: DetailedVotingRoom) => (a.details.name < b.details.name ? -1 : 1)
case VotingSortingEnum.ZtoA:
return (a: DetailedVotingRoom, b: DetailedVotingRoom) => (a.details.name < b.details.name ? 1 : -1)
case VotingSortingEnum.EndingLatest:
return (a: DetailedVotingRoom, b: DetailedVotingRoom) => {
return a.endAt < b.endAt ? -1 : 1
}
case VotingSortingEnum.EndingSoonest:
return (a: DetailedVotingRoom, b: DetailedVotingRoom) => {
return a.endAt < b.endAt ? 1 : -1
}
case VotingSortingEnum.MostVotes:
return (a: DetailedVotingRoom, b: DetailedVotingRoom) => {
const aSum = a.totalVotesAgainst.add(a.totalVotesFor)
const bSum = b.totalVotesAgainst.add(b.totalVotesFor)
return aSum < bSum ? 1 : -1
}
case VotingSortingEnum.LeastVotes:
return (a: DetailedVotingRoom, b: DetailedVotingRoom) => {
const aSum = a.totalVotesAgainst.add(a.totalVotesFor)
const bSum = b.totalVotesAgainst.add(b.totalVotesFor)
return aSum < bSum ? -1 : 1
}
}
}
export function sortDirectoryFunction(sortedBy: DirectorySortingEnum) {
switch (sortedBy) {
case DirectorySortingEnum.AtoZ:
return (a: CommunityDetail, b: CommunityDetail) => (a.name < b.name ? -1 : 1)
case DirectorySortingEnum.ZtoA:
return (a: CommunityDetail, b: CommunityDetail) => (a.name < b.name ? 1 : -1)
case DirectorySortingEnum.IncludedLongAgo:
return (a: CommunityDetail, b: CommunityDetail) => {
if (!a.directoryInfo) return 1
if (!b.directoryInfo) return -1
return a?.directoryInfo?.additionDate < b?.directoryInfo?.additionDate ? -1 : 1
}
case DirectorySortingEnum.IncludedRecently:
return (a: CommunityDetail, b: CommunityDetail) => {
if (!a.directoryInfo) return -1
if (!b.directoryInfo) return 1
return a?.directoryInfo?.additionDate < b?.directoryInfo?.additionDate ? 1 : -1
}
case DirectorySortingEnum.MostVotes:
return (a: CommunityDetail, b: CommunityDetail) => {
if (!a.directoryInfo?.featureVotes) return 1
if (!b.directoryInfo?.featureVotes) return -1
return a?.directoryInfo?.featureVotes < b?.directoryInfo?.featureVotes ? 1 : -1
}
case DirectorySortingEnum.LeastVotes:
return (a: CommunityDetail, b: CommunityDetail) => {
if (!a.directoryInfo?.featureVotes) return 1
if (!b.directoryInfo?.featureVotes) return -1
return a?.directoryInfo?.featureVotes < b?.directoryInfo?.featureVotes ? -1 : 1
}
}
}

View File

@ -2,19 +2,22 @@ import { useEthers } from '@usedapp/core'
import { useConfig } from '../providers/config'
import { Contract } from '@usedapp/core/node_modules/ethers'
import { Interface } from '@ethersproject/abi'
import { MockContract } from '@status-community-dapp/contracts/abi'
import { MockContract, Directory } from '@status-community-dapp/contracts/abi'
export function useContracts() {
const { config } = useConfig()
const { chainId } = useEthers()
let votingContract = new Contract('0x0000000000000000000000000000000000000000', new Interface(MockContract.abi))
let directoryContract = new Contract('0x0000000000000000000000000000000000000000', new Interface(Directory.abi))
if (chainId) {
const chainConfig = config.contracts[chainId]
if (chainConfig) {
votingContract = new Contract(chainConfig.votingContract, new Interface(MockContract.abi))
directoryContract = new Contract(chainConfig.directoryContract, new Interface(Directory.abi))
}
}
return { votingContract }
return { votingContract, directoryContract }
}

View File

@ -0,0 +1,41 @@
import { useContractCall } from '@usedapp/core'
import { useEffect, useState } from 'react'
import { getCommunityDetails } from '../helpers/apiMock'
import { isTextInDetails, sortDirectoryFunction } from '../helpers/communityFiltering'
import { CommunityDetail, DirectorySortingEnum } from '../models/community'
import { useContracts } from './useContracts'
export function useDirectoryCommunities(filterKeyword: string, sortedBy: DirectorySortingEnum) {
const { directoryContract } = useContracts()
const [communities] = useContractCall({
abi: directoryContract.interface,
address: directoryContract.address,
method: 'getCommunities',
args: [],
}) ?? [[]]
const [unfilteredComm, setUnfilteredComm] = useState(communities)
const [filteredCommunities, setFilteredCommunities] = useState<CommunityDetail[]>([])
useEffect(() => {
const getDetails = async () => {
if (communities.length > 0) {
const detailedComm = await Promise.all(communities.map(async (key: string) => await getCommunityDetails(key)))
setUnfilteredComm(detailedComm)
}
}
getDetails()
}, [JSON.stringify(communities)])
useEffect(() => {
const filterCommunities = unfilteredComm.filter((comm: CommunityDetail) => {
if (comm) {
return isTextInDetails(filterKeyword, comm)
}
return false
})
setFilteredCommunities(filterCommunities.sort(sortDirectoryFunction(sortedBy)))
}, [unfilteredComm, sortedBy, filterKeyword])
return filteredCommunities
}

View File

@ -4,56 +4,7 @@ import { getCommunityDetails } from '../helpers/apiMock'
import { VotingSortingEnum } from '../models/community'
import { DetailedVotingRoom } from '../models/smartContract'
import { useContracts } from './useContracts'
function isTextInRoom(filterKeyword: string, room: any) {
return (
room.details.name.toLowerCase().includes(filterKeyword.toLowerCase()) ||
room.details.description.toLowerCase().includes(filterKeyword.toLowerCase()) ||
room.details.tags.findIndex((item: any) => filterKeyword.toLowerCase() === item.toLowerCase()) > -1
)
}
function isTypeInRoom(voteType: string, room: any) {
if (!voteType) {
return true
}
if (voteType === 'Add') {
return room.voteType === 1
}
if (voteType === 'Remove') {
return room.voteType === 0
}
return false
}
function sortFunction(sortedBy: VotingSortingEnum) {
switch (sortedBy) {
case VotingSortingEnum.AtoZ:
return (a: DetailedVotingRoom, b: DetailedVotingRoom) => (a.details.name < b.details.name ? -1 : 1)
case VotingSortingEnum.ZtoA:
return (a: DetailedVotingRoom, b: DetailedVotingRoom) => (a.details.name < b.details.name ? 1 : -1)
case VotingSortingEnum.EndingLatest:
return (a: DetailedVotingRoom, b: DetailedVotingRoom) => {
return a.endAt < b.endAt ? -1 : 1
}
case VotingSortingEnum.EndingSoonest:
return (a: DetailedVotingRoom, b: DetailedVotingRoom) => {
return a.endAt < b.endAt ? 1 : -1
}
case VotingSortingEnum.MostVotes:
return (a: DetailedVotingRoom, b: DetailedVotingRoom) => {
const aSum = a.totalVotesAgainst.add(a.totalVotesFor)
const bSum = b.totalVotesAgainst.add(b.totalVotesFor)
return aSum < bSum ? 1 : -1
}
case VotingSortingEnum.LeastVotes:
return (a: DetailedVotingRoom, b: DetailedVotingRoom) => {
const aSum = a.totalVotesAgainst.add(a.totalVotesFor)
const bSum = b.totalVotesAgainst.add(b.totalVotesFor)
return aSum < bSum ? -1 : 1
}
}
}
import { isTextInDetails, isTypeInRoom, sortVotingFunction } from '../helpers/communityFiltering'
export function useVotingCommunities(
filterKeyword: string,
@ -102,11 +53,11 @@ export function useVotingCommunities(
useEffect(() => {
const filteredRooms = roomsWithCommunity.filter((room: any) => {
if (room) {
return isTextInRoom(filterKeyword, room) && isTypeInRoom(voteType, room)
return isTextInDetails(filterKeyword, room.details) && isTypeInRoom(voteType, room)
}
return false
})
setFilteredRooms(filteredRooms.sort(sortFunction(sortedBy)))
setFilteredRooms(filteredRooms.sort(sortVotingFunction(sortedBy)))
}, [roomsWithCommunity, filterKeyword, voteType, sortedBy])
return filteredRooms

View File

@ -2,6 +2,7 @@ import React from 'react'
import { render } from 'react-dom'
import { App } from './App'
import { DAppProvider, ChainId } from '@usedapp/core'
import { DEFAULT_CONFIG } from '@usedapp/core/dist/cjs/src/model/config/default'
import { ConfigProvider } from './providers/config/provider'
import { WakuProvider } from './providers/waku/provider'
@ -10,6 +11,11 @@ const config = {
readOnlyUrls: {
[ChainId.Ropsten]: 'https://ropsten.infura.io/v3/b4451d780cc64a078ccf2181e872cfcf',
},
multicallAddresses: {
...DEFAULT_CONFIG.multicallAddresses,
1337: '0x049e017b504F85d3c07AFE712fC79501aa1DB712',
},
supportedChains: [...DEFAULT_CONFIG.supportedChains, 1337],
}
render(

View File

@ -16,23 +16,28 @@ interface EnvConfigs {
const contracts = {
3: {
votingContract: '0x942C8248d14c20b9E79d7A60178B5b17Dd7186c3',
votingContract: '0xDAd243C1D47f25b129001181F09c53F93B66c721',
directoryContract: '0x78055B8E0fD4a130f4D3536EfdcF0A5617077D24',
},
1337: {
votingContract: '0x7623410b03A75B75133488032886c1E6Fb58222f',
directoryContract: '0xD17456480B991979a2882395a5Def44F8C48282C',
},
}
export const config: EnvConfigs = {
localhost: {
wakuTopic: `/myApp/localhost/${uuidv4()}/0.0.2/votingRoom/`,
wakuTopic: `/myApp/localhost/${uuidv4()}/0.0.3/votingRoom/`,
numberPerPage: 2,
contracts,
},
development: {
wakuTopic: '/myApp/development/0.0.2/votingRoom/',
wakuTopic: '/myApp/development/0.0.3/votingRoom/',
numberPerPage: 3,
contracts,
},
production: {
wakuTopic: '/myApp/production/0.0.2/votingRoom/',
wakuTopic: '/myApp/production/0.0.3/votingRoom/',
numberPerPage: 4,
contracts,
},

View File

@ -1,3 +1,4 @@
import MockContract from './../build/MockContract.json'
import Directory from './../build/Directory.json'
export { MockContract }
export { MockContract, Directory }

View File

@ -0,0 +1,25 @@
import { ethers } from 'ethers'
import { deployContract } from 'ethereum-waffle'
import MockContract from '../build/MockContract.json'
import Directory from '../build/Directory.json'
const deploy = async () => {
const providerName = process.env.ETHEREUM_PROVIDER
const privateKey = process.env.ETHEREUM_PRIVATE_KEY
console.log(privateKey)
if (privateKey && providerName) {
console.log(`deploying on ${providerName}`)
const provider = ethers.getDefaultProvider(process.env.ETHEREUM_PROVIDER)
const wallet = new ethers.Wallet(privateKey, provider)
const mockContract = await deployContract(wallet, MockContract)
console.log(`Voting contract deployed with address: ${mockContract.address}`)
const directoryContract = await deployContract(wallet,Directory,[mockContract.address])
await mockContract.setDirectory(directoryContract.address)
console.log(`Directory contract deployed with address: ${directoryContract.address}`)
}
}
deploy()

View File

@ -78,7 +78,7 @@ describe('Contract', () => {
await provider.send('evm_mine', [Math.floor(Date.now() / 1000)])
return { contract, directory, alice, firstAddress, secondAddress, provider }
}
loadFixture(fixture)
it('deploys properly', async () => {
const { contract, directory } = await loadFixture(fixture)
expect(await contract.directory()).to.eq(directory.address)