From 50d417b89800a6c9968d4ebdffaa9fb5334ee74b Mon Sep 17 00:00:00 2001 From: yuetloo Date: Thu, 24 Feb 2022 13:19:17 -0500 Subject: [PATCH 01/98] create panel component shared by project list and metadata list --- vue-app/src/components/Panel.vue | 25 +++++++++++++++++++++++++ vue-app/src/views/ProjectList.vue | 15 ++++----------- 2 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 vue-app/src/components/Panel.vue diff --git a/vue-app/src/components/Panel.vue b/vue-app/src/components/Panel.vue new file mode 100644 index 000000000..671688671 --- /dev/null +++ b/vue-app/src/components/Panel.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/vue-app/src/views/ProjectList.vue b/vue-app/src/views/ProjectList.vue index b068643c1..00ebf4d7c 100644 --- a/vue-app/src/views/ProjectList.vue +++ b/vue-app/src/views/ProjectList.vue @@ -55,12 +55,12 @@ > - +
Date: Thu, 24 Feb 2022 13:19:48 -0500 Subject: [PATCH 02/98] refactoring, move recipient data definition out of optimistic registry --- .../src/api/recipient-registry-optimistic.ts | 62 +----------------- vue-app/src/api/recipient.ts | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+), 61 deletions(-) create mode 100644 vue-app/src/api/recipient.ts diff --git a/vue-app/src/api/recipient-registry-optimistic.ts b/vue-app/src/api/recipient-registry-optimistic.ts index 58b38c81f..50ad10e4b 100644 --- a/vue-app/src/api/recipient-registry-optimistic.ts +++ b/vue-app/src/api/recipient-registry-optimistic.ts @@ -13,6 +13,7 @@ import { provider, ipfsGatewayUrl, recipientRegistryPolicy } from './core' import { Project } from './projects' import sdk from '@/graphql/sdk' import { Recipient } from '@/graphql/API' +import { RecipientApplicationData } from './recipient' export interface RegistryInfo { deposit: BigNumber @@ -62,67 +63,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 diff --git a/vue-app/src/api/recipient.ts b/vue-app/src/api/recipient.ts new file mode 100644 index 000000000..cfc1f79f8 --- /dev/null +++ b/vue-app/src/api/recipient.ts @@ -0,0 +1,64 @@ +import { Project } from './projects' +import { ipfsGatewayUrl } from './core' + +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 + 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, + } +} From 576e574c9837bb24f885b67cd03d9474691b41cc Mon Sep 17 00:00:00 2001 From: yuetloo Date: Thu, 24 Feb 2022 13:20:16 -0500 Subject: [PATCH 03/98] fix warning on modifying props --- vue-app/src/components/Links.vue | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/vue-app/src/components/Links.vue b/vue-app/src/components/Links.vue index 934456610..6c84256ad 100644 --- a/vue-app/src/components/Links.vue +++ b/vue-app/src/components/Links.vue @@ -2,14 +2,14 @@ - + @@ -26,14 +26,18 @@ export default class extends Vue { @Prop() hideArrow!: boolean @Prop() ariaLabel!: string - isExternal = false + get destination(): string | { [key: string]: any } { + return this.href ?? this.to + } - mounted() { - if (this.href) { - this.to = this.href - } - if (typeof this.to === 'string') { - this.isExternal = this.to.includes('http') || this.to.includes('mailto:') + get isExternal(): boolean { + if (typeof this.destination === 'string') { + return ( + this.destination.includes('http') || + this.destination.includes('mailto:') + ) + } else { + return false } } } From 619fd08237835ccbd5c81488fa99ae8cd273d3d1 Mon Sep 17 00:00:00 2001 From: yuetloo Date: Thu, 24 Feb 2022 13:20:33 -0500 Subject: [PATCH 04/98] initial work for metadata registry integration --- subgraph/config/rinkeby.json | 6 + vue-app/package.json | 1 + vue-app/src/App.vue | 8 + vue-app/src/api/core.ts | 9 + vue-app/src/api/ipfs.ts | 12 + vue-app/src/api/metadata.ts | 312 ++++ vue-app/src/components/Box.vue | 41 + vue-app/src/components/ClickableCard.vue | 37 + vue-app/src/components/FormNavigation.vue | 9 +- vue-app/src/components/FormProgressWidget.vue | 5 +- .../components/MetadataSubmissionWidget.vue | 306 ++++ vue-app/src/components/NavBar.vue | 5 + vue-app/src/components/SearchInput.vue | 73 + vue-app/src/plugins/Web3/constants/chains.ts | 18 + vue-app/src/store/getters.ts | 6 +- vue-app/src/store/mutations.ts | 14 +- vue-app/src/views/Join.vue | 1351 +---------------- vue-app/src/views/JoinLanding.vue | 4 +- vue-app/src/views/Metadata.vue | 55 + vue-app/src/views/MetadataForm.vue | 1310 ++++++++++++++++ vue-app/src/views/MetadataFormAdd.vue | 60 + vue-app/src/views/MetadataFormEdit.vue | 66 + vue-app/src/views/MetadataList.vue | 204 +++ vue-app/src/views/MetadataRegistry.vue | 24 + vue-app/src/views/MetadataViewer.vue | 413 +++++ vue-app/tests/unit/ipfs.spec.ts | 12 + yarn.lock | 417 +++++ 27 files changed, 3483 insertions(+), 1295 deletions(-) create mode 100644 subgraph/config/rinkeby.json create mode 100644 vue-app/src/api/ipfs.ts create mode 100644 vue-app/src/api/metadata.ts create mode 100644 vue-app/src/components/Box.vue create mode 100644 vue-app/src/components/ClickableCard.vue create mode 100644 vue-app/src/components/MetadataSubmissionWidget.vue create mode 100644 vue-app/src/components/SearchInput.vue create mode 100644 vue-app/src/views/Metadata.vue create mode 100644 vue-app/src/views/MetadataForm.vue create mode 100644 vue-app/src/views/MetadataFormAdd.vue create mode 100644 vue-app/src/views/MetadataFormEdit.vue create mode 100644 vue-app/src/views/MetadataList.vue create mode 100644 vue-app/src/views/MetadataRegistry.vue create mode 100644 vue-app/src/views/MetadataViewer.vue create mode 100644 vue-app/tests/unit/ipfs.spec.ts diff --git a/subgraph/config/rinkeby.json b/subgraph/config/rinkeby.json new file mode 100644 index 000000000..434b744c9 --- /dev/null +++ b/subgraph/config/rinkeby.json @@ -0,0 +1,6 @@ +{ + "network": "rinkeby", + "address": "0x93A990D939Ca592cD8cCa47b7a0c3F590A598F9d", + "factoryStartBlock": 9969110, + "recipientRegistryStartBlock": 9969130 +} diff --git a/vue-app/package.json b/vue-app/package.json index 1f0ac6b57..c2f033fa0 100644 --- a/vue-app/package.json +++ b/vue-app/package.json @@ -15,6 +15,7 @@ "@kleros/gtcr-encoder": "^1.4.0", "@openfonts/inter_all": "^1.0.2", "@walletconnect/web3-provider": "^1.5.1", + "@yuetloo/metadata-composer": "^1.0.10", "core-js": "^3.6.4", "crypto-js": "^4.0.0", "ethereum-blockies-base64": "^1.0.2", diff --git a/vue-app/src/App.vue b/vue-app/src/App.vue index 0d435a313..fb5f4a39b 100644 --- a/vue-app/src/App.vue +++ b/vue-app/src/App.vue @@ -152,6 +152,10 @@ export default class App extends Vue { 'verify', 'verify-step', 'verified', + 'metadata', + 'metadata-registry', + 'metadata-edit', + 'metadata-new', ] return !excludedRoutes.includes(this.$route.name || '') } @@ -166,6 +170,10 @@ export default class App extends Vue { 'verify', 'verify-step', 'verified', + 'metadata', + 'metadata-registry', + 'metadata-edit', + 'metadata-new', ] return !excludedRoutes.includes(this.$route.name || '') } diff --git a/vue-app/src/api/core.ts b/vue-app/src/api/core.ts index 39ca1168c..37076993e 100644 --- a/vue-app/src/api/core.ts +++ b/vue-app/src/api/core.ts @@ -52,3 +52,12 @@ export const extraRounds: string[] = process.env.VUE_APP_EXTRA_ROUNDS export const SUBGRAPH_ENDPOINT = process.env.VUE_APP_SUBGRAPH_URL || 'https://api.thegraph.com/subgraphs/name/daodesigner/clrfund' + +export const METADATA_SUBGRAPH_URL_PREFIX = process.env + .VUE_APP_METADATA_SUBGRAPH_URL_PREFIX + ? process.env.VUE_APP_METADATA_SUBGRAPH_URL_PREFIX + : 'https://api.thegraph.com/subgraphs/name/yuetloo/metadata-' + +export const METADATA_NETWORKS = process.env.VUE_APP_METADATA_NETWORKS + ? process.env.VUE_APP_METADATA_NETWORKS.split(',') + : ['rinkeby'] diff --git a/vue-app/src/api/ipfs.ts b/vue-app/src/api/ipfs.ts new file mode 100644 index 000000000..c390dbb20 --- /dev/null +++ b/vue-app/src/api/ipfs.ts @@ -0,0 +1,12 @@ +import { ipfsGatewayUrl } from './core' + +export class Ipfs { + static toUrl(hash: string | undefined): string | undefined { + if (!hash) { + return + } + + const base = ipfsGatewayUrl || '' + return new URL(`/ipfs/${hash}`, base).toString() + } +} diff --git a/vue-app/src/api/metadata.ts b/vue-app/src/api/metadata.ts new file mode 100644 index 000000000..05ca01c9a --- /dev/null +++ b/vue-app/src/api/metadata.ts @@ -0,0 +1,312 @@ +import { MetadataComposer, SearchOptions } from '@yuetloo/metadata-composer' +import { ContractTransaction, providers, ContractReceipt } from 'ethers' +import { METADATA_NETWORKS, METADATA_SUBGRAPH_URL_PREFIX, chain } from './core' +import { Project } from './projects' +import { Ipfs } from './ipfs' +import { resolveEns } from '@/utils/accounts' +import { RecipientApplicationData } from './recipient' + +const urls = METADATA_NETWORKS.map( + (network) => `${METADATA_SUBGRAPH_URL_PREFIX}${network}` +) + +const composer = new MetadataComposer(urls) + +/** + * Extract address for the given chain + * @param receivingAddresses array of EIP-3770 addresses, i.e. eth:0x11111... + * @param chainShortName chain short name + * @returns address for the 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] +} + +/** + * Parse and populate receiving addresses + * @param data data containing receivingAddresses + * @returns metadata populated with resolvedAddress and addressName + */ +async function populateAddresses(data: any): Promise { + const addressName = getAddressForChain( + data.receivingAddresses, + chain.shortName + ) + + let hasEns = false + let resolvedAddress = addressName + if (addressName) { + let res: string | null = null + try { + res = await resolveEns(addressName) + } catch { + // ignore error, the application should + // flag this as missing required field + } + hasEns = !!res + resolvedAddress = res ? res : addressName + } + + return { + ...data, + hasEns, + addressName, + resolvedAddress, + } +} + +/** + * format the address according to EIP3770 format, i.e. eth:0x123... + * @param address address to format + * @returns EIP3770 format address + */ +function toEIP3770Address(address: string): string { + return `${chain.shortName}:${address}` +} + +/** + * Metadata class + */ +export class Metadata { + id?: string + name?: string + owner?: string + receivingAddresses?: string[] + addressName?: string + resolvedAddress?: string + hasEns: boolean + tagline?: string + description?: string + category?: string + problemSpace?: string + plans?: string + teamName?: string + teamDescription?: string + githubUrl?: string + radicleUrl?: string + websiteUrl?: string + twitterUrl?: string + discordUrl?: string + bannerImageHash?: string + thumbnailImageHash?: string + imageHash?: string + + constructor(data: any) { + this.id = data.id + this.name = data.name + this.owner = data.owner + this.addressName = data.addressName + this.resolvedAddress = data.resolvedAddress + this.receivingAddresses = data.receivingAddresses + this.hasEns = !!data.hasEns + this.tagline = data.tagline + this.description = data.description + this.category = data.category + this.problemSpace = data.problemSpace + this.plans = data.plans + this.teamName = data.teamName + this.teamDescription = data.teamDescription + this.githubUrl = data.githubUrl + this.radicleUrl = data.radicleUrl + this.websiteUrl = data.websiteUrl + this.twitterUrl = data.twitterUrl + this.discordUrl = data.discordUrl + this.bannerImageHash = data.bannerImageHash + this.thumbnailImageHash = data.thumbnailImageHash + this.imageHash = data.imageHash + } + + /** + * Search metadata by search text + * @param searchText search for metadata containing this text + * @param options first - option to limit search result + * activeOnly - option to search only active metadata (not deleted) + * @returns array of metadata + */ + static async search( + searchText: string, + options: SearchOptions + ): Promise { + const result = await composer.search(searchText, options) + if (result.error) { + throw new Error(result.error) + } + + const { data = [] } = result + const ensResult = await Promise.all(data.map(populateAddresses)) + return ensResult.map((entry) => new Metadata(entry)) + } + + /** + * Get metadata by id + * @param id metadata id + * @returns metadata + */ + static async get(id: string): Promise { + const result = await composer.get(id) + if (result.error) { + throw new Error(result.error) + } + + const { data } = result + if (!data) { + return null + } + + const arg = await populateAddresses(data) + return new Metadata({ ...arg }) + } + + /** + * Convert metadata to project interface + * @returns project + */ + toProject(): Project { + return { + id: this.id || '', + address: this.resolvedAddress || '', + name: this.name || '', + tagline: this.tagline, + description: this.description || '', + category: this.category, + problemSpace: this.problemSpace, + plans: this.plans, + teamName: this.teamName, + teamDescription: this.teamDescription, + githubUrl: this.githubUrl, + radicleUrl: this.radicleUrl, + websiteUrl: this.websiteUrl, + twitterUrl: this.twitterUrl, + discordUrl: this.discordUrl, + bannerImageUrl: Ipfs.toUrl(this.bannerImageHash), + thumbnailImageUrl: Ipfs.toUrl(this.thumbnailImageHash), + imageUrl: Ipfs.toUrl(this.imageHash), + index: 0, + isHidden: false, + isLocked: false, + } + } + + /** + * Convert metadata to recipient application form data + * @returns recipient application form data + */ + toRecipient(): RecipientApplicationData { + return { + project: { + name: this.name || '', + tagline: this.tagline || '', + description: this.description || '', + category: this.category || '', + problemSpace: this.problemSpace || '', + }, + fund: { + addressName: this.addressName || '', + resolvedAddress: this.resolvedAddress || '', + plans: this.plans || '', + }, + team: { + name: this.teamName || '', + description: this.teamDescription || '', + email: '', // TODO: populate this + }, + links: { + github: this.githubUrl || '', + radicle: this.radicleUrl || '', + website: this.websiteUrl || '', + twitter: this.twitterUrl || '', + discord: this.discordUrl || '', + }, + image: { + bannerHash: this.bannerImageHash || '', + thumbnailHash: this.thumbnailImageHash || '', + }, + furthestStep: 0, + hasEns: this.hasEns || false, + id: this.id, + } + } + + /** + * Convert recipient form data to Metadata + * @param data recipient application form data + * @returns Metadata + */ + static fromFormData(data: RecipientApplicationData): Metadata { + const { id, project, fund, team, links, image } = data + return new Metadata({ + id, + name: project.name, + tagline: project.tagline, + description: project.description, + category: project.category, + problemSpace: project.problemSpace, + plans: fund.plans, + receivingAddresses: [toEIP3770Address(fund.resolvedAddress)], + addressName: fund.addressName, + resolvedAddress: fund.resolvedAddress, + 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, + }) + } + + /** + * Create a metadata in the registry + * @param web3 EIP1193 web3 provider used to sign the transaction + * @returns transaction handle + */ + async create(web3: providers.Web3Provider): Promise { + return composer.create(this, web3.provider) + } + + /** + * Update metadata in the registry + * @param web3 provider used to sign the transaction + * @returns transaction handle + */ + async update(web3: providers.Web3Provider): Promise { + if (!this.id) { + throw new Error('Unable to update metadata, id missing') + } + const metadata = { ...this, target: this.id } + return composer.update(metadata, web3.provider) + } + + /** + * Delete metadata to registry + * @param web3 provider used to sign the delete transaction + * @returns transaction handle + */ + async delete(web3: providers.Web3Provider): Promise { + if (!this.id) { + throw new Error('Unable to delete metadata, id missing') + } + return composer.delete(this.id, web3.provider) + } + + /** + * Get metadata id from the receipt + * @param receipt receipt containing the metadata transaction + * @returns metadata id + */ + static getMetadataId(receipt: ContractReceipt): string { + const event = (receipt.events || []).find((e) => e.event === 'NewPost') + return `${chain.subgraphNetwork}-${receipt.transactionHash}-${event?.logIndex}` + } +} diff --git a/vue-app/src/components/Box.vue b/vue-app/src/components/Box.vue new file mode 100644 index 000000000..3f4fa4229 --- /dev/null +++ b/vue-app/src/components/Box.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/vue-app/src/components/ClickableCard.vue b/vue-app/src/components/ClickableCard.vue new file mode 100644 index 000000000..6633791fd --- /dev/null +++ b/vue-app/src/components/ClickableCard.vue @@ -0,0 +1,37 @@ + + + + + diff --git a/vue-app/src/components/FormNavigation.vue b/vue-app/src/components/FormNavigation.vue index 6dd7e058e..a36250d79 100644 --- a/vue-app/src/components/FormNavigation.vue +++ b/vue-app/src/components/FormNavigation.vue @@ -33,7 +33,7 @@ export default class FormNavigation extends Vue { @Prop() steps!: string[] @Prop() isStepValid!: boolean @Prop() callback!: (updateFurthest?: boolean) => void - @Prop() handleStepNav!: () => void + @Prop() handleStepNav!: (step: number) => void @Prop() isNavDisabled!: boolean // TODO is this needed? Why do we pass `callback` & `handleStepNav`? @@ -41,12 +41,7 @@ export default class FormNavigation extends Vue { // Save form data (first saves when user hits Next after first step) this.callback(true) // "true" checks to update furthest step // Navigate forward - this.$router.push({ - name: 'join-step', - params: { - step: this.steps[this.currentStep + 1], - }, - }) + this.handleStepNav(this.currentStep + 1) } handlePrev(): void { diff --git a/vue-app/src/components/FormProgressWidget.vue b/vue-app/src/components/FormProgressWidget.vue index f40276ddc..fb639d0bb 100644 --- a/vue-app/src/components/FormProgressWidget.vue +++ b/vue-app/src/components/FormProgressWidget.vue @@ -52,7 +52,7 @@ />

Step {{ currentStep + 1 }} of {{ steps.length }}

- Cancel + Cancel
@@ -83,8 +83,9 @@ export default class FormProgressWidget extends Vue { @Prop() isNavDisabled!: boolean @Prop() isStepUnlocked!: (step: number) => boolean @Prop() isStepValid!: (step: number) => boolean - @Prop() handleStepNav!: () => void + @Prop() handleStepNav!: (step: number) => void @Prop() saveFormData!: (updateFurthest?: boolean) => void + @Prop() cancelRedirectUrl!: string } diff --git a/vue-app/src/components/MetadataSubmissionWidget.vue b/vue-app/src/components/MetadataSubmissionWidget.vue new file mode 100644 index 000000000..712e1c98a --- /dev/null +++ b/vue-app/src/components/MetadataSubmissionWidget.vue @@ -0,0 +1,306 @@ + + + + + diff --git a/vue-app/src/components/NavBar.vue b/vue-app/src/components/NavBar.vue index cb0dffd77..df0f03565 100644 --- a/vue-app/src/components/NavBar.vue +++ b/vue-app/src/components/NavBar.vue @@ -69,6 +69,11 @@ export default class NavBar extends Vue { text: 'Code', emoji: '๐Ÿ‘พ', }, + { + to: '/metadata', + text: 'Manage metadata', + emoji: '๐Ÿ“ƒ', + }, ] created() { diff --git a/vue-app/src/components/SearchInput.vue b/vue-app/src/components/SearchInput.vue new file mode 100644 index 000000000..291d51f03 --- /dev/null +++ b/vue-app/src/components/SearchInput.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/vue-app/src/plugins/Web3/constants/chains.ts b/vue-app/src/plugins/Web3/constants/chains.ts index ddbe7f63a..34f899971 100644 --- a/vue-app/src/plugins/Web3/constants/chains.ts +++ b/vue-app/src/plugins/Web3/constants/chains.ts @@ -20,6 +20,8 @@ export interface ChainInfo { explorerLabel: string rpcUrl?: string bridge?: string + shortName: string + subgraphNetwork: string } } @@ -32,6 +34,8 @@ export const CHAIN_INFO: ChainInfo = { explorer: 'https://etherscan.io', explorerLogo: 'etherscan.svg', explorerLabel: 'Etherscan', + shortName: 'eth', + subgraphNetwork: 'mainnet', }, [ChainId.RINKEBY]: { label: 'Rinkeby', @@ -41,6 +45,8 @@ export const CHAIN_INFO: ChainInfo = { explorer: 'https://rinkeby.etherscan.io', explorerLogo: 'etherscan.svg', explorerLabel: 'Etherscan', + shortName: 'rin', + subgraphNetwork: 'rinkeby', }, [ChainId.HARDHAT]: { label: 'Arbitrum Hardhat', @@ -52,6 +58,8 @@ export const CHAIN_INFO: ChainInfo = { explorerLabel: 'Arbiscan', rpcUrl: 'https://rinkeby.arbitrum.io/rpc', bridge: 'https://bridge.arbitrum.io', + shortName: 'got', + subgraphNetwork: 'arbitrum-rinkeby', }, [ChainId.ARBITRUM_ONE]: { label: 'Arbitrum', @@ -63,6 +71,8 @@ export const CHAIN_INFO: ChainInfo = { explorerLabel: 'Arbiscan', rpcUrl: 'https://arb1.arbitrum.io/rpc', bridge: 'https://bridge.arbitrum.io', + shortName: 'arb1', + subgraphNetwork: 'arbitrum-one', }, [ChainId.ARBITRUM_RINKEBY]: { label: 'Arbitrum Rinkeby', @@ -74,6 +84,8 @@ export const CHAIN_INFO: ChainInfo = { explorerLabel: 'Arbiscan', rpcUrl: 'https://rinkeby.arbitrum.io/rpc', bridge: 'https://bridge.arbitrum.io', + shortName: 'arb-rinkeby', + subgraphNetwork: 'arbitrum-rinkeby', }, [ChainId.OPTIMISM]: { label: 'Optimism', @@ -85,6 +97,8 @@ export const CHAIN_INFO: ChainInfo = { explorerLabel: 'Etherscan', rpcUrl: 'https://mainnet.optimism.io', bridge: 'https://gateway.optimism.io', + shortName: 'oeth', + subgraphNetwork: 'optimism', }, [ChainId.XDAI]: { label: 'xDai', @@ -96,6 +110,8 @@ export const CHAIN_INFO: ChainInfo = { explorerLabel: 'Blockscout', rpcUrl: 'https://rpc.xdaichain.com/', bridge: 'https://bridge.xdaichain.com', + shortName: 'gno', + subgraphNetwork: 'xdai', }, [ChainId.POLYGON]: { label: 'Polygon', @@ -107,5 +123,7 @@ export const CHAIN_INFO: ChainInfo = { explorerLabel: 'Polygonscan', rpcUrl: 'https://rpc-mainnet.matic.network', bridge: 'https://wallet.polygon.technology', + shortName: 'MATIC', + subgraphNetwork: 'matic', }, } diff --git a/vue-app/src/store/getters.ts b/vue-app/src/store/getters.ts index 51ca3cf6f..0732c5956 100644 --- a/vue-app/src/store/getters.ts +++ b/vue-app/src/store/getters.ts @@ -9,10 +9,8 @@ import { RoundInfo, RoundStatus } from '@/api/round' import { Tally } from '@/api/tally' import { User } from '@/api/user' import { Factory } from '@/api/factory' -import { - RecipientApplicationData, - RegistryInfo, -} from '@/api/recipient-registry-optimistic' +import { RegistryInfo } from '@/api/recipient-registry-optimistic' +import { RecipientApplicationData } from '@/api/recipient' // Utils import { isSameAddress } from '@/utils/accounts' diff --git a/vue-app/src/store/mutations.ts b/vue-app/src/store/mutations.ts index 8faaf7ab6..5d9877d66 100644 --- a/vue-app/src/store/mutations.ts +++ b/vue-app/src/store/mutations.ts @@ -8,10 +8,8 @@ import { RoundInfo } from '@/api/round' import { Tally } from '@/api/tally' import { User } from '@/api/user' import { Factory } from '@/api/factory' -import { - RecipientApplicationData, - RegistryInfo, -} from '@/api/recipient-registry-optimistic' +import { RegistryInfo } from '@/api/recipient-registry-optimistic' +import { RecipientApplicationData } from '@/api/recipient' // Constants import { @@ -137,15 +135,9 @@ const mutations = { state, payload: { updatedData: RecipientApplicationData - step: string - stepNumber: number } ) { - if (!state.recipient) { - state.recipient = payload.updatedData - } else { - state.recipient[payload.step] = payload.updatedData[payload.step] - } + state.recipient = payload.updatedData }, [RESET_RECIPIENT_DATA](state) { state.recipient = null diff --git a/vue-app/src/views/Join.vue b/vue-app/src/views/Join.vue index 45a24e488..84b464b8d 100644 --- a/vue-app/src/views/Join.vue +++ b/vue-app/src/views/Join.vue @@ -11,699 +11,24 @@ :isStepValid="isStepValid" :handleStepNav="handleStepNav" :saveFormData="saveFormData" + cancelRedirectUrl="/join" />

Join the round

-
-
-

- Review info -

-

- Preview project -

-
-
Cancel
-
+ +
-

About the project

-
-
- - -

- Your project needs a name -

-
-
- -

- Describe your project in a sentence. Max characters: 140 -

-