Skip to content

Commit

Permalink
add metadata validation and code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
yuetloo committed Jul 26, 2022
1 parent da5a299 commit ba0dd13
Show file tree
Hide file tree
Showing 12 changed files with 554 additions and 388 deletions.
1 change: 1 addition & 0 deletions vue-app/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ export default class App extends Vue {
'join-step',
'round-information',
'transaction-success',
'metadata-success',
'verify',
'verify-step',
'verified',
Expand Down
123 changes: 57 additions & 66 deletions vue-app/src/api/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { METADATA_NETWORKS, METADATA_SUBGRAPH_URL_PREFIX, chain } from './core'
import { Project } from './projects'
import { Ipfs } from './ipfs'
import { MAX_RETRIES } from './core'
import { required, url } from 'vuelidate/lib/validators'
import { required, url, maxLength } from 'vuelidate/lib/validators'
import * as isIPFS from 'is-ipfs'
import { ReceivingAddress } from '@/api/receiving-address'

const subgraphUrl = (network: string): string =>
`${METADATA_SUBGRAPH_URL_PREFIX}${network}`
Expand Down Expand Up @@ -40,6 +42,7 @@ export interface MetadataFormData {
}
fund: {
receivingAddresses: string[]
currentChainReceivingAddress: string
plans: string
}
team: {
Expand All @@ -65,39 +68,56 @@ export interface MetadataFormData {
owner?: string
}

export const MetadataValidations = {
id: { required },
name: { required },
tagline: { required },
description: { required },
category: { required },
problemSpace: { required },
githubUrl: { url },
radicleUrl: { url },
websiteUrl: { url },
twitterUrl: { url },
discordUrl: { url },
bannerImageHash: { required },
thumbnailImageHash: { required },
export const MetadataFormValidations = {
project: {
name: { required },
tagline: {
required,
maxLength: maxLength(140),
},
description: { required },
category: { required },
problemSpace: { required },
},
fund: {
receivingAddresses: {},
currentChainReceivingAddress: {
required,
validEthAddress: utils.isAddress,
},
plans: { required },
},
team: {
name: {},
description: {},
},
links: {
github: { url },
radicle: { url },
website: { url },
twitter: { url },
discord: { url },
},
image: {
bannerHash: {
required,
validIpfsHash: isIPFS.cid,
},
thumbnailHash: {
required,
validIpfsHash: isIPFS.cid,
},
},
}

/**
* Extract address for the given chain
* Extract address for the current chain from the fund receiving addresses
* @param receivingAddresses array of EIP-3770 addresses, i.e. eth:0x11111...
* @param chainShortName chain short name
* @returns address for the chain
* @returns address for the current chain
*/
function getAddressForChain(
receivingAddresses: string[] = [],
chainShortName: string
): string {
const chainAddresses = receivingAddresses.reduce((addresses, data) => {
const [chainName, address] = data.split(':')
addresses[chainName] = address
return addresses
}, {})

return chainAddresses[chainShortName]
function getAddressForCurrentChain(receivingAddresses: string[] = []): string {
const addresses = ReceivingAddress.fromArray(receivingAddresses)
return addresses[chain.shortName]
}

/**
Expand All @@ -121,23 +141,6 @@ async function getLatestBlock(network: string): Promise<number> {
return meta.block.number
}

/**
* Parse and populate receiving addresses
* @param data data containing receivingAddresses
* @returns metadata populated with resolvedAddress and addressName
*/
async function populateAddresses(data: any): Promise<Metadata> {
const addressName = getAddressForChain(
data.receivingAddresses,
chain.shortName
)

return {
...data,
addressName,
}
}

function sleep(factor: number): Promise<void> {
const timeout = factor ** 2 * 1000
return new Promise((resolve) => setTimeout(resolve, timeout))
Expand All @@ -152,8 +155,7 @@ export class Metadata {
owner?: string
network?: string
receivingAddresses?: string[]
addressName?: string
resolvedAddress?: string
currentChainReceivingAddress?: string
tagline?: string
description?: string
category?: string
Expand All @@ -179,6 +181,9 @@ export class Metadata {
this.owner = data.owner
this.network = data.network
this.receivingAddresses = data.receivingAddresses
this.currentChainReceivingAddress = getAddressForCurrentChain(
data.receivingAddresses
)
this.tagline = data.tagline
this.description = data.description
this.category = data.category
Expand Down Expand Up @@ -233,8 +238,7 @@ export class Metadata {
return null
}

const arg = await populateAddresses(data)
return new Metadata({ ...arg })
return new Metadata({ ...data })
}

/**
Expand All @@ -252,29 +256,14 @@ export class Metadata {
return result.data?.metadataEntries || []
}

/**
* get the receiving address of the current chain
* @param addresses list of EIP3770 addresses
* @returns the address of the current chain
*/
getCurrentChainAddress(addresses: string[] = []): string {
const chainPrefix = chain.shortName + ':'
const chainAddress = addresses.find((addr) => {
return addr.startsWith(chainPrefix)
})

return chainAddress ? chainAddress.substring(chainPrefix.length) : ''
}

/**
* Convert metadata to project interface
* @returns project
*/
toProject(): Project {
const address = this.getCurrentChainAddress(this.receivingAddresses)
return {
id: this.id || '',
address,
address: this.currentChainReceivingAddress || '',
name: this.name || '',
tagline: this.tagline,
description: this.description || '',
Expand Down Expand Up @@ -312,6 +301,8 @@ export class Metadata {
},
fund: {
receivingAddresses: this.receivingAddresses || [],
currentChainReceivingAddress:
getAddressForCurrentChain(this.receivingAddresses) || '',
plans: this.plans || '',
},
team: {
Expand Down
36 changes: 36 additions & 0 deletions vue-app/src/api/receiving-address.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Fund Receiving Address
*/
export class ReceivingAddress {
/**
* Convert the receiving addresses from string to a lookup dictionary
* @param addresses array of EIP3770 addresses (e.g. eth:0x1234...)
* @returns a dictionary of chain short name to address
*/
static fromArray(addresses: string[]): Record<string, string> {
const result: Record<string, string> = addresses.reduce(
(addresses, item) => {
const chainAddress = item.split(':')

if (chainAddress.length === 2) {
addresses[chainAddress[0]] = chainAddress[1]
}
return addresses
},
{}
)

return result
}

/**
* Convert a chain-address dictionary to an array of EIP3770 addresses
* @param addresses a dictionary with chain short name to address
* @returns an array of EIP3770 addresses
*/
static toArray(addresses: Record<string, string>): string[] {
return Object.entries(addresses).map(
([chain, address]) => `${chain}:${address}`
)
}
}
32 changes: 4 additions & 28 deletions vue-app/src/api/recipient-registry-optimistic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import {
import { getEventArg } from '@/utils/contracts'

import { OptimisticRecipientRegistry } from './abi'
import { RecipientApplicationData } from './recipient'
import { RecipientRegistryInterface } from './types'
import { Metadata } from './metadata'
import { MetadataFormData } from './metadata'
import { chain } from './core'

// TODO merge this with `Project` inteface
Expand All @@ -33,33 +32,9 @@ export interface RecipientData {
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(
registryAddress: string,
recipientMetadata: Metadata,
recipientMetadata: MetadataFormData,
deposit: BigNumber,
signer: Signer
): Promise<TransactionResponse> {
Expand All @@ -68,11 +43,12 @@ export async function addRecipient(
OptimisticRecipientRegistry,
signer
)
const { id, address } = recipientMetadata.toProject()
const { id, fund } = recipientMetadata
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`)
}
Expand Down
31 changes: 0 additions & 31 deletions vue-app/src/api/recipient.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import { Project } from './projects'
import { ipfsGatewayUrl } from './core'

export interface RecipientApplicationData {
project: {
name: string
Expand Down Expand Up @@ -35,31 +32,3 @@ export interface RecipientApplicationData {
hasEns: boolean
id?: string
}

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,
}
}
Loading

0 comments on commit ba0dd13

Please sign in to comment.