Skip to content

Commit

Permalink
Merge pull request #676 from clrfund/fix/simple-user-registry-ui
Browse files Browse the repository at this point in the history
Update UI for simple user registry and simple recipient registry
  • Loading branch information
yuetloo authored Jun 14, 2023
2 parents cebf251 + b721c8f commit d2a28d6
Show file tree
Hide file tree
Showing 18 changed files with 320 additions and 175 deletions.
3 changes: 3 additions & 0 deletions vue-app/src/api/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,6 @@ const leaderboardRounds = historicalRounds as LeaderboardRound[]
export { leaderboardRounds }

export const showComplianceRequirement = /^yes$/i.test(import.meta.env.VITE_SHOW_COMPLIANCE_REQUIREMENT)

export const isBrightIdRequired = userRegistryType === 'brightid'
export const isOptimisticRecipientRegistry = recipientRegistryType === 'optimistic'
27 changes: 27 additions & 0 deletions vue-app/src/api/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import OptimisticRegistry from './recipient-registry-optimistic'
import KlerosRegistry from './recipient-registry-kleros'
import sdk from '@/graphql/sdk'
import { getLeaderboardData } from '@/api/leaderboard'
import type { RecipientApplicationData } from '@/api/types'

export interface LeaderboardProject {
id: string // Address or another ID depending on registry implementation
Expand Down Expand Up @@ -231,3 +232,29 @@ export async function getLeaderboardProject(
isLocked: true, // Visible, but contributions are not allowed
}
}

export function formToProjectInterface(data: RecipientApplicationData): Project {
const { project, fund, team, links, image } = data
return {
id: fund.resolvedAddress,
address: fund.resolvedAddress,
name: project.name,
tagline: project.tagline,
description: project.description,
category: project.category,
problemSpace: project.problemSpace,
plans: fund.plans,
teamName: team.name,
teamDescription: team.description,
githubUrl: links.github,
radicleUrl: links.radicle,
websiteUrl: links.website,
twitterUrl: links.twitter,
discordUrl: links.discord,
bannerImageUrl: `${ipfsGatewayUrl}/ipfs/${image.bannerHash}`,
thumbnailImageUrl: `${ipfsGatewayUrl}/ipfs/${image.thumbnailHash}`,
index: 0,
isHidden: false,
isLocked: true,
}
}
31 changes: 29 additions & 2 deletions vue-app/src/api/recipient-registry-kleros.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Contract, type Event, Signer } from 'ethers'
import { Contract, type Event, Signer, BigNumber } from 'ethers'
import type { TransactionResponse } from '@ethersproject/abstract-provider'
import { gtcrDecode } from '@kleros/gtcr-encoder'

import { KlerosGTCR, KlerosGTCRAdapter } from './abi'
import { provider, ipfsGatewayUrl } from './core'
import type { Project } from './projects'
import type { RegistryInfo } from './types'

const KLEROS_CURATE_URL = 'https://curate.kleros.io/tcr/0x2E3B10aBf091cdc53cC892A50daBDb432e220398'

Expand Down Expand Up @@ -179,4 +180,30 @@ export async function registerProject(
return transaction
}

export default { getProjects, getProject, registerProject }
async function getRegistryInfo(registryAddress: string): Promise<RegistryInfo> {
const registry = new Contract(registryAddress, KlerosGTCRAdapter, provider)

let recipientCount
try {
recipientCount = await registry.getRecipientCount()
} catch {
// older BaseRecipientRegistry contract did not have recipientCount
// set it to zero as this information is only
// used during current round for space calculation
recipientCount = BigNumber.from(0)
}

// Kleros registry does not have owner
const owner = ''

// deposit, depositToken and challengePeriodDuration are only relevant to the optimistic registry
return {
deposit: BigNumber.from(0),
depositToken: '',
challengePeriodDuration: 0,
recipientCount: recipientCount.toNumber(),
owner,
}
}

export default { getProjects, getProject, registerProject, getRegistryInfo }
123 changes: 6 additions & 117 deletions vue-app/src/api/recipient-registry-optimistic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,15 @@ import { getEventArg } from '@/utils/contracts'
import { chain } from '@/api/core'

import { OptimisticRecipientRegistry } from './abi'
import { provider, ipfsGatewayUrl, recipientRegistryPolicy } from './core'
import { provider, ipfsGatewayUrl } from './core'
import type { Project } from './projects'
import sdk from '@/graphql/sdk'
import type { Recipient } from '@/graphql/API'
import { hasDateElapsed } from '@/utils/dates'
import type { RegistryInfo, RecipientApplicationData } from './types'
import { formToRecipientData } from './recipient'

export interface RegistryInfo {
deposit: BigNumber
depositToken: string
challengePeriodDuration: number
listingPolicyUrl: string
recipientCount: number
owner: string
}

export async function getRegistryInfo(registryAddress: string): Promise<RegistryInfo> {
async function getRegistryInfo(registryAddress: string): Promise<RegistryInfo> {
const registry = new Contract(registryAddress, OptimisticRecipientRegistry, provider)
const deposit = await registry.baseDeposit()
const challengePeriodDuration = await registry.challengePeriodDuration()
Expand All @@ -39,7 +32,6 @@ export async function getRegistryInfo(registryAddress: string): Promise<Registry
deposit,
depositToken: chain.currency,
challengePeriodDuration: challengePeriodDuration.toNumber(),
listingPolicyUrl: `${ipfsGatewayUrl}/ipfs/${recipientRegistryPolicy}`,
recipientCount: recipientCount.toNumber(),
owner,
}
Expand All @@ -63,65 +55,6 @@ export enum RequestStatus {
Removed = 'Removed',
}

export interface RecipientApplicationData {
project: {
name: string
tagline: string
description: string
category: string
problemSpace: string
}
fund: {
addressName: string
resolvedAddress: string
plans: string
}
team: {
name: string
description: string
email: string
}
links: {
github: string
radicle: string
website: string
twitter: string
discord: string
}
image: {
bannerHash: string
thumbnailHash: string
}
furthestStep: number
hasEns: boolean
}

export function formToProjectInterface(data: RecipientApplicationData): Project {
const { project, fund, team, links, image } = data
return {
id: fund.resolvedAddress,
address: fund.resolvedAddress,
name: project.name,
tagline: project.tagline,
description: project.description,
category: project.category,
problemSpace: project.problemSpace,
plans: fund.plans,
teamName: team.name,
teamDescription: team.description,
githubUrl: links.github,
radicleUrl: links.radicle,
websiteUrl: links.website,
twitterUrl: links.twitter,
discordUrl: links.discord,
bannerImageUrl: `${ipfsGatewayUrl}/ipfs/${image.bannerHash}`,
thumbnailImageUrl: `${ipfsGatewayUrl}/ipfs/${image.thumbnailHash}`,
index: 0,
isHidden: false,
isLocked: true,
}
}

interface RecipientMetadata {
name: string
description: string
Expand Down Expand Up @@ -207,51 +140,7 @@ export async function getRequests(registryInfo: RegistryInfo, registryAddress: s
return Object.keys(requests).map(recipientId => requests[recipientId])
}

// TODO merge this with `Project` inteface
export interface RecipientData {
name: string
description: string
imageHash?: string // TODO remove - old flow
address: string
tagline?: string
category?: string
problemSpace?: string
plans?: string
teamName?: string
teamDescription?: string
githubUrl?: string
radicleUrl?: string
websiteUrl?: string
twitterUrl?: string
discordUrl?: string
// fields different vs. Project
bannerImageHash?: string
thumbnailImageHash?: string
}

export function formToRecipientData(data: RecipientApplicationData): RecipientData {
const { project, fund, team, links, image } = data
return {
address: fund.resolvedAddress,
name: project.name,
tagline: project.tagline,
description: project.description,
category: project.category,
problemSpace: project.problemSpace,
plans: fund.plans,
teamName: team.name,
teamDescription: team.description,
githubUrl: links.github,
radicleUrl: links.radicle,
websiteUrl: links.website,
twitterUrl: links.twitter,
discordUrl: links.discord,
bannerImageHash: image.bannerHash,
thumbnailImageHash: image.thumbnailHash,
}
}

export async function addRecipient(
async function addRecipient(
registryAddress: string,
recipientApplicationData: RecipientApplicationData,
deposit: BigNumber,
Expand Down Expand Up @@ -455,4 +344,4 @@ export async function removeProject(registryAddress: string, recipientId: string
return transaction
}

export default { getProjects, getProject, registerProject, decodeProject }
export default { getProjects, getProject, registerProject, decodeProject, getRegistryInfo, addRecipient }
58 changes: 55 additions & 3 deletions vue-app/src/api/recipient-registry-simple.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,36 @@
import { Contract } from 'ethers'
import { Contract, BigNumber, Signer } from 'ethers'
import type { Event } from 'ethers'
import { isHexString } from '@ethersproject/bytes'
import type { TransactionResponse } from '@ethersproject/abstract-provider'

import { SimpleRecipientRegistry } from './abi'
import { provider, ipfsGatewayUrl } from './core'
import type { Project } from './projects'
import type { RegistryInfo, RecipientApplicationData } from './types'
import { formToRecipientData } from './recipient'

function decodeRecipientAdded(event: Event): Project {
const args = event.args as any
const metadata = JSON.parse(args._metadata)
console.log('metata', metadata)
return {
id: args._recipientId,
address: args._recipient,
name: metadata.name,
description: metadata.description,
imageUrl: `${ipfsGatewayUrl}/ipfs/${metadata.imageHash}`,
tagline: metadata.tagline,
category: metadata.category,
problemSpace: metadata.problemSpace,
plans: metadata.plans,
teamName: metadata.teamName,
teamDescription: metadata.teamDescription,
githubUrl: metadata.githubUrl,
radicleUrl: metadata.radicleUrl,
websiteUrl: metadata.websiteUrl,
twitterUrl: metadata.twitterUrl,
discordUrl: metadata.discordUrl,
bannerImageUrl: `${ipfsGatewayUrl}/ipfs/${metadata.bannerImageHash}`,
thumbnailImageUrl: `${ipfsGatewayUrl}/ipfs/${metadata.thumbnailImageHash}`,
index: args._index.toNumber(),
isHidden: false,
isLocked: false,
Expand Down Expand Up @@ -90,4 +106,40 @@ export async function getProject(registryAddress: string, recipientId: string):
return project
}

export default { getProjects, getProject }
async function getRegistryInfo(registryAddress: string): Promise<RegistryInfo> {
const registry = new Contract(registryAddress, SimpleRecipientRegistry, provider)

let recipientCount
try {
recipientCount = await registry.getRecipientCount()
} catch {
// older BaseRecipientRegistry contract did not have recipientCount
// set it to zero as this information is only
// used during current round for space calculation
recipientCount = BigNumber.from(0)
}
const owner = await registry.owner()

// deposit, depositToken and challengePeriodDuration are only relevant to the optimistic registry
return {
deposit: BigNumber.from(0),
depositToken: '',
challengePeriodDuration: 0,
recipientCount: recipientCount.toNumber(),
owner,
}
}

async function addRecipient(
registryAddress: string,
recipientApplicationData: RecipientApplicationData,
signer: Signer,
): Promise<TransactionResponse> {
const registry = new Contract(registryAddress, SimpleRecipientRegistry, signer)
const recipientData = formToRecipientData(recipientApplicationData)
const { address, ...metadata } = recipientData
const transaction = await registry.addRecipient(address, JSON.stringify(metadata))
return transaction
}

export default { getProjects, getProject, getRegistryInfo, addRecipient }
36 changes: 36 additions & 0 deletions vue-app/src/api/recipient-registry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { RegistryInfo, RecipientApplicationData } from './types'
import { recipientRegistryType } from './core'
import SimpleRegistry from './recipient-registry-simple'
import OptimisticRegistry from './recipient-registry-optimistic'
import KlerosRegistry from './recipient-registry-kleros'
import type { BigNumber, Signer } from 'ethers'
import type { TransactionResponse } from '@ethersproject/abstract-provider'

export async function getRegistryInfo(registryAddress: string): Promise<RegistryInfo> {
if (recipientRegistryType === 'simple') {
return await SimpleRegistry.getRegistryInfo(registryAddress)
} else if (recipientRegistryType === 'optimistic') {
return await OptimisticRegistry.getRegistryInfo(registryAddress)
} else if (recipientRegistryType === 'kleros') {
return await KlerosRegistry.getRegistryInfo(registryAddress)
} else {
throw new Error('Invalid recipient registry type: ' + recipientRegistryType)
}
}

export async function addRecipient(
registryAddress: string,
recipientApplicationData: RecipientApplicationData,
deposit: BigNumber,
signer: Signer,
): Promise<TransactionResponse> {
if (recipientRegistryType === 'simple') {
return await SimpleRegistry.addRecipient(registryAddress, recipientApplicationData, signer)
} else if (recipientRegistryType === 'optimistic') {
return await OptimisticRegistry.addRecipient(registryAddress, recipientApplicationData, deposit, signer)
} else if (recipientRegistryType === 'kleros') {
throw new Error('Kleros recipient registry is not supported')
} else {
throw new Error('Invalid recipient registry type: ' + recipientRegistryType)
}
}
Loading

0 comments on commit d2a28d6

Please sign in to comment.