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

Allow recipient registry owner to add recipients for simple recipient registry type #538

Merged
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
15 changes: 10 additions & 5 deletions contracts/scripts/deployRecipientRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ import { RecipientRegistryFactory } from '../utils/recipient-registry-factory'
async function main() {
const recipientRegistryType = process.env.RECIPIENT_REGISTRY_TYPE || 'simple'
const fundingRoundFactoryAddress = process.env.FUNDING_ROUND_FACTORY_ADDRESS
const challengePeriodDuration = process.env.CHALLENGE_PERIOD_IN_SECONDS || 300
const baseDeposit = process.env.BASE_DEPOSIT || UNIT.div(10).toString()
let challengePeriodDuration = '0'
let baseDeposit = '0'

if (recipientRegistryType === 'optimistic') {
challengePeriodDuration = process.env.CHALLENGE_PERIOD_IN_SECONDS || '300'
baseDeposit = process.env.BASE_DEPOSIT || UNIT.div(10).toString()
}

if (!fundingRoundFactoryAddress) {
console.log('Environment variable FUNDING_ROUND_FACTORY_ADDRESS not set')
Expand All @@ -35,9 +40,9 @@ async function main() {
console.log('*******************')
console.log(`Deploying a new ${recipientRegistryType} recipient registry!`)
console.log(` challenge period in seconds: ${challengePeriodDuration}`)
console.log(` baseDeposit ${baseDeposit}`)
console.log(` fundingRoundFactoryAddress ${fundingRoundFactoryAddress}`)
console.log(` fundingRoundFactoryOwner ${factoryOwner}`)
console.log(` baseDeposit: ${baseDeposit}`)
console.log(` fundingRoundFactoryAddress: ${fundingRoundFactoryAddress}`)
console.log(` fundingRoundFactoryOwner: ${factoryOwner}`)
const [deployer] = await ethers.getSigners()

const recipientRegistry = await RecipientRegistryFactory.deploy(
Expand Down
24 changes: 12 additions & 12 deletions subgraph/src/MACIMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ import { FundingRound, Message, PublicKey } from '../generated/schema'
// - contract.verifier(...)

export function handlePublishMessage(event: PublishMessage): void {
const fundingRoundId = event.transaction.to.toHexString()
let fundingRoundId = event.transaction.to.toHexString()
if (fundingRoundId == null) {
log.error(
'Error: handlePublishMessage failed fundingRound not registered',
[]
)
return
}
const fundingRound = FundingRound.load(fundingRoundId)
let fundingRound = FundingRound.load(fundingRoundId)
if (fundingRound == null) {
log.error(
'Error: handlePublishMessage failed fundingRound not registered',
Expand All @@ -37,23 +37,23 @@ export function handlePublishMessage(event: PublishMessage): void {
return
}

const messageID = event.transaction.hash.toHexString()
let messageID = event.transaction.hash.toHexString()

const timestamp = event.block.timestamp.toString()
const message = new Message(messageID)
let timestamp = event.block.timestamp.toString()
let message = new Message(messageID)
message.data = event.params._message.data
message.iv = event.params._message.iv

const publicKeyId = event.transaction.from.toHexString()
const publicKey = PublicKey.load(publicKeyId)
let publicKeyId = event.transaction.from.toHexString()
let publicKey = PublicKey.load(publicKeyId)

//NOTE: If the public keys aren't being tracked initialize them
if (publicKey == null) {
const publicKey = new PublicKey(publicKeyId)
let publicKey = new PublicKey(publicKeyId)
publicKey.x = event.params._encPubKey.x
publicKey.y = event.params._encPubKey.y

const _messages = [messageID] as string[]
let _messages = [messageID] as string[]
publicKey.messages = _messages
publicKey.fundingRound = fundingRoundId

Expand All @@ -68,12 +68,12 @@ export function handlePublishMessage(event: PublishMessage): void {
}

export function handleSignUp(event: SignUp): void {
const publicKeyId = event.transaction.from.toHexString()
const publicKey = PublicKey.load(publicKeyId)
let publicKeyId = event.transaction.from.toHexString()
let publicKey = PublicKey.load(publicKeyId)

//NOTE: If the public keys aren't being tracked initialize them
if (publicKey == null) {
const publicKey = new PublicKey(publicKeyId)
let publicKey = new PublicKey(publicKeyId)
publicKey.x = event.params._userPubKey.x
publicKey.y = event.params._userPubKey.y
publicKey.stateIndex = event.params._stateIndex
Expand Down
6 changes: 4 additions & 2 deletions subgraph/src/RecipientMapping.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Recipient } from '../generated/schema'

export const RECIPIENT_REQUEST_TYPE_REGISTRATION = '0'
export const RECIPIENT_REQUEST_TYPE_REMOVAL = '1'

export function removeRecipient(id: string, timestamp: string): void {
let recipient = Recipient.load(id)
if (recipient) {
// TODO: should we hard delete the recipient record?
recipient.rejected = true
recipient.requestType = RECIPIENT_REQUEST_TYPE_REMOVAL
recipient.lastUpdatedAt = timestamp
recipient.save()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@ import {
} from '../../generated/templates/KlerosRecipientRegistry/KlerosRecipientRegistry'

import { Recipient } from '../../generated/schema'
import { removeRecipient } from '../RecipientMapping'
import {
removeRecipient,
RECIPIENT_REQUEST_TYPE_REGISTRATION,
} from '../RecipientMapping'

export function handleRecipientAdded(event: RecipientAdded): void {
let recipientRegistryId = event.address.toHexString()

let recipientId = event.params._tcrItemId.toHexString()
let recipient = new Recipient(recipientId)
recipient.requestType = RECIPIENT_REQUEST_TYPE_REGISTRATION
// recipient was verified by kleros
recipient.verified = true
recipient.recipientRegistry = recipientRegistryId
recipient.createdAt = event.block.timestamp.toString()
recipient.recipientIndex = event.params._index
Expand Down
2 changes: 1 addition & 1 deletion subgraph/src/recipientRegistry/RecipientRegistryType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export enum RecipientRegistryType {

let registryTypeMap = new TypedMap<string, RecipientRegistryType>()
registryTypeMap.set('simple', RecipientRegistryType.Simple)
registryTypeMap.set('klerso', RecipientRegistryType.Kleros)
registryTypeMap.set('kleros', RecipientRegistryType.Kleros)
registryTypeMap.set('optimistic', RecipientRegistryType.Optimistic)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import {
} from '../../generated/templates/SimpleRecipientRegistry/SimpleRecipientRegistry'

import { Recipient } from '../../generated/schema'
import { removeRecipient } from '../RecipientMapping'
import {
removeRecipient,
RECIPIENT_REQUEST_TYPE_REGISTRATION,
} from '../RecipientMapping'

export function handleRecipientAdded(event: RecipientAdded): void {
let recipientRegistryId = event.address.toHexString()
Expand All @@ -13,12 +16,15 @@ export function handleRecipientAdded(event: RecipientAdded): void {
let recipient = new Recipient(recipientId)

recipient.requester = event.transaction.from.toHexString()
recipient.requestType = RECIPIENT_REQUEST_TYPE_REGISTRATION
recipient.recipientRegistry = recipientRegistryId
recipient.recipientMetadata = event.params._metadata
recipient.recipientIndex = event.params._index
recipient.recipientAddress = event.params._recipient
recipient.submissionTime = event.params._timestamp.toString()
recipient.requestResolvedHash = event.transaction.hash
// recipients are verified as they are added by the admin
recipient.verified = true
recipient.createdAt = event.block.timestamp.toString()

recipient.save()
Expand Down
8 changes: 4 additions & 4 deletions vue-app/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,16 @@ VUE_APP_GOOGLE_SPREADSHEET_ID=

# metadata registry configurations
# The networks where metadata is stored; as comma separated strings
# i.e. rinkeby,ropsten,mainnet
# i.e. arbitrum-rinkeby,ropsten,mainnet
VUE_APP_METADATA_NETWORKS=

# metadata registry subgraph url prefix
# Add the network part (VUE_APP_METADATA_NETWORKS) to form the complete url
# i.e. https://api.thegraph.com/subgraphs/name/yuetloo/metadata-
METADATA_SUBGRAPH_URL_PREFIX=
# i.e. https://api.thegraph.com/subgraphs/name/clrfund/metadata-
VUE_APP_METADATA_SUBGRAPH_URL_PREFIX=

# subgraph query batch size, default to 30
QUERY_BATCH_SIZE=
VUE_APP_QUERY_BATCH_SIZE=

# Select the sheet's name to write the data, by default 'Raw'
GOOGLE_SHEET_NAME=
3 changes: 2 additions & 1 deletion vue-app/src/api/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ export const METADATA_NETWORKS = process.env.VUE_APP_METADATA_NETWORKS
? process.env.VUE_APP_METADATA_NETWORKS.split(',')
: ['rinkeby']

export const QUERY_BATCH_SIZE = Number(process.env.QUERY_BATCH_SIZE) || 30
export const QUERY_BATCH_SIZE =
Number(process.env.VUE_APP_QUERY_BATCH_SIZE) || 30

export const MAX_RETRIES = Number(process.env.VUE_APP_MAX_RETRIES) || 10

Expand Down
9 changes: 2 additions & 7 deletions vue-app/src/api/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
recipientRegistryType,
} from './core'

import SimpleRegistry from './recipient-registry-simple'
import KlerosRegistry from './recipient-registry-kleros'
import RecipientRegistry from './recipient-registry'

Expand Down Expand Up @@ -57,9 +56,7 @@ export async function getProjects(
startTime?: number,
endTime?: number
): Promise<Project[]> {
if (recipientRegistryType === 'simple') {
return await SimpleRegistry.getProjects(registryAddress, startTime, endTime)
} else if (recipientRegistryType === 'kleros') {
if (recipientRegistryType === 'kleros') {
return await KlerosRegistry.getProjects(registryAddress, startTime, endTime)
} else {
return await RecipientRegistry.getProjects(
Expand All @@ -74,9 +71,7 @@ export async function getProject(
registryAddress: string,
recipientId: string
): Promise<Project | null> {
if (recipientRegistryType === 'simple') {
return await SimpleRegistry.getProject(registryAddress, recipientId)
} else if (recipientRegistryType === 'kleros') {
if (recipientRegistryType === 'kleros') {
return await KlerosRegistry.getProject(registryAddress, recipientId)
} else {
return await RecipientRegistry.getProject(recipientId)
Expand Down
4 changes: 2 additions & 2 deletions vue-app/src/api/recipient-registry-kleros.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,8 @@ export function create(): RecipientRegistryInterface {
removeProject,
registerProject,
rejectProject,
isRegistrationOpen: true,
requireRegistrationDeposit: true,
isSelfRegistration: false, //TODO: add support for self registration
requireRegistrationDeposit: false,
}
}

Expand Down
2 changes: 1 addition & 1 deletion vue-app/src/api/recipient-registry-optimistic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export function create(): RecipientRegistryInterface {
registerProject,
removeProject,
rejectProject,
isRegistrationOpen: true,
isSelfRegistration: true,
requireRegistrationDeposit: true,
}
}
Expand Down
36 changes: 28 additions & 8 deletions vue-app/src/api/recipient-registry-simple.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { BigNumber, Contract, Event, Signer } from 'ethers'
import { TransactionResponse } from '@ethersproject/abstract-provider'
import { ContractTransaction } from '@ethersproject/contracts'

import { isHexString } from '@ethersproject/bytes'

import { SimpleRecipientRegistry } from './abi'
import { provider, ipfsGatewayUrl } from './core'
import { provider, ipfsGatewayUrl, chain } from './core'
import { RecipientRegistryInterface } from './types'
import { Project, toProjectInterface } from './projects'

Expand Down Expand Up @@ -122,18 +123,37 @@ export function addRecipient(
recipientData: any,
_deposit: BigNumber,
signer: Signer
): Promise<TransactionResponse> {
): Promise<ContractTransaction> {
const registry = new Contract(
registryAddress,
SimpleRecipientRegistry,
signer
)
const { address, ...metadata } = recipientData
return registry.addRecipient(address, JSON.stringify(metadata))
const { id, fund } = recipientData
if (!id) {
throw new Error('Missing metadata id')
}

const { currentChainReceivingAddress: address } = fund
if (!address) {
throw new Error(`Missing recipient address for the ${chain.name} network`)
}

const json = { id }
return registry.addRecipient(address, JSON.stringify(json))
}

function removeProject() {
throw new Error('removeProject not implemented')
function removeProject(
registryAddress: string,
recipientId: string,
signer: Signer
): Promise<ContractTransaction> {
const registry = new Contract(
registryAddress,
SimpleRecipientRegistry,
signer
)
return registry.removeRecipient(recipientId)
}

function rejectProject() {
Expand All @@ -150,7 +170,7 @@ export function create(): RecipientRegistryInterface {
removeProject,
registerProject,
rejectProject,
isRegistrationOpen: false,
isSelfRegistration: false,
requireRegistrationDeposit: false,
}
}
Expand Down
33 changes: 28 additions & 5 deletions vue-app/src/api/recipient-registry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BigNumber, Contract } from 'ethers'
import { BigNumber, Contract, Signer } from 'ethers'
import sdk from '@/graphql/sdk'
import { BaseRecipientRegistry } from './abi'
import {
Expand All @@ -23,7 +23,7 @@ import KlerosRegistry from './recipient-registry-kleros'
import { isHexString } from '@ethersproject/bytes'
import { Recipient } from '@/graphql/API'
import { Project } from './projects'
import { Metadata } from './metadata'
import { Metadata, MetadataFormData } from './metadata'
import { DateTime } from 'luxon'

const registryLookup: Record<RecipientRegistryType, Function> = {
Expand Down Expand Up @@ -74,7 +74,7 @@ export async function getRegistryInfo(
listingPolicyUrl: `${ipfsGatewayUrl}/ipfs/${recipientRegistryPolicy}`,
recipientCount: recipientCount.toNumber(),
owner,
isRegistrationOpen: registry.isRegistrationOpen,
isSelfRegistration: registry.isSelfRegistration,
requireRegistrationDeposit: registry.requireRegistrationDeposit,
}
}
Expand Down Expand Up @@ -342,11 +342,19 @@ export async function getRequests(
const requestType = Number(recipient.requestType)
if (requestType === RequestTypeCode.Registration) {
// Registration request
const { name, description, imageHash, thumbnailImageHash } = metadata
const {
name,
description,
imageHash,
bannerImageHash,
thumbnailImageHash,
} = metadata

metadata = {
name,
description,
imageUrl: `${ipfsGatewayUrl}/ipfs/${imageHash}`,
bannerImageUrl: `${ipfsGatewayUrl}/ipfs/${bannerImageHash}`,
thumbnailImageUrl: thumbnailImageHash
? `${ipfsGatewayUrl}/ipfs/${thumbnailImageHash}`
: `${ipfsGatewayUrl}/ipfs/${imageHash}`,
Expand Down Expand Up @@ -393,4 +401,19 @@ export async function getRequests(
return Object.keys(requests).map((recipientId) => requests[recipientId])
}

export default { getProject, getProjects, projectExists }
export async function addRecipient(
registryAddress: string,
recipientMetadata: MetadataFormData,
deposit: BigNumber,
signer: Signer
) {
const registry = RecipientRegistry.create(recipientRegistryType)
return registry.addRecipient(
registryAddress,
recipientMetadata,
deposit,
signer
)
}

export default { addRecipient, getProject, getProjects, projectExists }
Loading