Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into feat/maci-v1
Browse files Browse the repository at this point in the history
  • Loading branch information
yuetloo committed Jul 5, 2023
2 parents 2fb9fda + a610bfa commit c2d9ced
Show file tree
Hide file tree
Showing 74 changed files with 2,542 additions and 511 deletions.
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
16.14.2
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ to run `yarn test` or `yarn test:contracts`.
- [Vuelidate](https://vuelidate-next.netlify.app/)
- [vue-final-modal](https://vue-final-modal.org)
- [Ethers](https://docs.ethers.io/v5/)
- [Gun](https://gun.eco/docs/)

### Visual Studio Code

Expand Down
1 change: 1 addition & 0 deletions contracts/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ proofs.json
tally.json
.env
.DS_Store
tasks/addresses.txt
2 changes: 1 addition & 1 deletion contracts/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@clrfund/contracts",
"version": "4.1.1",
"version": "4.2.3",
"license": "GPL-3.0",
"scripts": {
"hardhat": "hardhat",
Expand Down
1 change: 1 addition & 0 deletions contracts/tasks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ import './fetchRound'
import './mergeAllocations'
import './setDurations'
import './deploySponsor'
import './loadUsers'
89 changes: 89 additions & 0 deletions contracts/tasks/loadUsers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { task } from 'hardhat/config'
import { Contract, utils, ContractReceipt } from 'ethers'
import fs from 'fs'

/*
* Script to bulkload users into the simple user registry.
* File path can be relative or absolute path.
* The script can only be run by the owner of the simple user registry
*
* Sample usage:
*
* yarn hardhat load-users --file-path addresses.txt --user-registry <address> --network goerli
*/

/**
* Add a user to the Simple user registry
*
* @param registry Simple user registry contract
* @param address User wallet address
* @returns transaction receipt
*/
async function addUser(
registry: Contract,
address: string
): Promise<ContractReceipt> {
const tx = await registry.addUser(address)
const receipt = await tx.wait()
return receipt
}

/**
* Load users in the file into the simple user registry
*
* @param registry Simple user registry contract
* @param filePath The path of the file containing the addresses
*/
async function loadFile(registry: Contract, filePath: string) {
let content: string | null = null
try {
content = fs.readFileSync(filePath, 'utf8')
} catch (err) {
console.error('Failed to read file', filePath, err)
return
}

const addresses: string[] = []
content.split(/\r?\n/).forEach(async (address) => {
addresses.push(address)
})

for (let i = 0; i < addresses.length; i++) {
const address = addresses[i]
const isValidAddress = Boolean(address) && utils.isAddress(address)
if (isValidAddress) {
console.log('Adding address', address)
try {
const result = await addUser(registry, address)
if (result.status !== 1) {
throw new Error(
`Transaction ${result.transactionHash} failed with status ${result.status}`
)
}
} catch (err: any) {
if (err.reason) {
console.error('Failed to add address', address, err.reason)
} else {
console.error('Failed to add address', address, err)
}
}
} else {
console.warn('Skipping invalid address', address)
}
}
}

task('load-users', 'Bulkload recipients into the simple user registry')
.addParam('userRegistry', 'The simple user registry contract address')
.addParam(
'filePath',
'The path of the file containing addresses separated by newline'
)
.setAction(async ({ userRegistry, filePath }, { ethers }) => {
const registry = await ethers.getContractAt(
'SimpleUserRegistry',
userRegistry
)

await loadFile(registry, filePath)
})
4 changes: 3 additions & 1 deletion docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ BRIGHTID_SPONSOR=

1. Adjust the `/contracts/scripts/deploy.ts` as you wish.
2. Run `yarn hardhat run --network {network} scripts/deploy.ts` or use one of the `yarn deploy:{network}` available in `/contracts/package.json`.
3. To deploy a new funding round, update the .env file with the funding round factory address deployed in the previous step and run the `newRound.ts` script:
3. Make sure to save in a safe place the serializedCoordinatorPrivKey and the serializedCoordinatorPubKey, you are going to need them for the website and tallying the votes in future steps.
4. To deploy a new funding round, update the .env file with the funding round factory address and the COORDINATOR_PK (with serializedCoordinatorPrivKey) deployed in the previous step and run the `newRound.ts` script:

```
# .env
FACTORY_ADDRESS=
COORDINATOR_PK=
```

```
Expand Down
3 changes: 2 additions & 1 deletion subgraph/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@clrfund/subgraph",
"version": "4.1.1",
"version": "4.2.3",
"repository": "https://github.com/clrfund/monorepo/subgraph",
"keywords": [
"clr.fund",
Expand All @@ -17,6 +17,7 @@
"prepare:hardhat": "mustache config/hardhat.json subgraph.template.yaml > subgraph.yaml",
"prepare:arbitrum": "mustache config/arbitrum.json subgraph.template.yaml > subgraph.yaml",
"prepare:arbitrum-rinkeby": "mustache config/arbitrum-rinkeby.json subgraph.template.yaml > subgraph.yaml",
"prepare:arbitrum-goerli": "mustache config/arbitrum-goerli.json subgraph.template.yaml > subgraph.yaml",
"prepare:xdai": "mustache config/xdai.json subgraph.template.yaml > subgraph.yaml",
"codegen": "graph codegen",
"lint:js": "eslint 'src/*.ts'",
Expand Down
30 changes: 15 additions & 15 deletions subgraph/src/MACIMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,24 +91,24 @@ export function handleSignUp(event: SignUp): void {

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

publicKey.voiceCreditBalance = event.params._voiceCreditBalance
publicKey = new PublicKey(publicKeyId)
}
publicKey.x = event.params._userPubKey.x
publicKey.y = event.params._userPubKey.y
publicKey.stateIndex = event.params._stateIndex

let fundingRoundAddress = event.transaction.to!
let fundingRoundId = fundingRoundAddress.toHex()
let fundingRound = FundingRound.load(fundingRoundId)
if (fundingRound == null) {
log.error('Error: handleSignUp failed, fundingRound not registered', [])
return
}
publicKey.voiceCreditBalance = event.params._voiceCreditBalance

publicKey.fundingRound = fundingRoundId
publicKey.save()
let fundingRoundAddress = event.transaction.to!
let fundingRoundId = fundingRoundAddress.toHex()
let fundingRound = FundingRound.load(fundingRoundId)
if (fundingRound == null) {
log.error('Error: handleSignUp failed, fundingRound not registered', [])
return
}

publicKey.fundingRound = fundingRoundId
publicKey.save()

log.info('SignUp', [])
}
4 changes: 4 additions & 0 deletions vue-app/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,7 @@ VITE_EXPORT_BATCH_SIZE=

# This is only used for netlify function, sponsor.js, to avoid getting the 'fetch not found' error
AWS_LAMBDA_JS_RUNTIME=nodejs18.x

# This date will be used in the verify landing page. If not set or bad date format, a generic message will be displayed
# format: yyyy-MM-dd e.g. 2023-06-26
VITE_NEXT_ROUND_START_DATE=
31 changes: 16 additions & 15 deletions vue-app/README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
# [WIP] clrfund vue3-app
# Clrfund Frontend

## Development

### GCP VM using VSCode Remote - SSH
- /graph-node/docker
- `docker compose up -d` or `docker compose restart`
- /clrfund
- `yarn start:subgraph`
- `yarn start:node`
- `yarn deploy:local`
- Start a development instance

```
yarn serve
```

### Local
- /clrfund
- `yarn start:gun`
- /vue-app
- `yarn serve`
- /vue3-app
- `yarn dev`
- Runs static analysis on translation texts for missing or unused keys

```
yarn test:lint-i18n`
```

- Generate graphql API's

```
yarn codegen
```
9 changes: 4 additions & 5 deletions vue-app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@clrfund/vue-app",
"version": "4.1.1",
"version": "4.2.3",
"private": true,
"license": "GPL-3.0",
"scripts": {
Expand All @@ -14,7 +14,7 @@
"type-check": "yarn vue-tsc --noEmit",
"codegen": "graphql-codegen --config codegen.yml",
"build-map": "NODE_OPTIONS=--max-old-space-size=4096 vite build --sourcemap",
"test:lint-i18n": "vue-i18n-extract report --vueFiles 'src/**/*.?(vue)' --languageFiles 'src/locales/*.?(json)' --exclude dynamic"
"test:lint-i18n": "vue-i18n-extract report --vueFiles 'src/**/*.?(vue)' --languageFiles 'src/locales/*.?(json)' --exclude dynamic --exclude join.step1.address_requirement"
},
"lint-staged": {
"**/*.{js,ts,json,scss,css,vue}": [
Expand All @@ -39,8 +39,6 @@
"humanize-duration": "^3.27.3",
"is-ipfs": "^7.0.3",
"luxon": "^3.1.1",
"maci-crypto": "npm:@clrfund/[email protected]",
"maci-domainobjs": "npm:@clrfund/[email protected]",
"markdown-it": "^13.0.1",
"markdown-it-link-attributes": "^4.0.1",
"node-stdlib-browser": "^1.2.0",
Expand All @@ -50,7 +48,8 @@
"vue-final-modal": "^4.3.0",
"vue-i18n": "9",
"vue-meta": "3.0.0-alpha.8",
"vue-router": "4"
"vue-router": "4",
"@clrfund/maci-utils": "^0.0.1"
},
"devDependencies": {
"@graphql-codegen/cli": "^3.3.0",
Expand Down
3 changes: 2 additions & 1 deletion vue-app/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ const routeName = computed(() => route.name?.toString() || '')
const isUserAndRoundLoaded = computed(() => !!currentUser.value && !!currentRound.value)
const isInApp = computed(() => routeName.value !== 'landing')
const isVerifyStep = computed(() => routeName.value === 'verify-step')
const isSideCartShown = computed(() => !!currentUser.value && isSidebarShown.value && routeName.value !== 'cart')
const isSideCartShown = computed(() => isUserAndRoundLoaded.value && isSidebarShown.value && routeName.value !== 'cart')
const isCartPadding = computed(() => {
const routes = ['cart']
return routes.includes(routeName.value)
Expand Down Expand Up @@ -169,6 +169,7 @@ onMounted(async () => {
await appStore.loadMACIFactoryInfo()
await appStore.loadRoundInfo()
await recipientStore.loadRecipientRegistryInfo()
appStore.isAppReady = true
setupLoadIntervals()
})
Expand Down
2 changes: 1 addition & 1 deletion vue-app/src/api/bright-id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ export async function brightIdSponsor(userAddress: string): Promise<SponsorData>
}

const message = JSON.stringify(op)
const arrayedMessage = Buffer.from(message)
const arrayedMessage = utils.toUtf8Bytes(message)
const arrayedKey = utils.base64.decode(brightIdSponsorKey)
const signature = nacl.sign.detached(arrayedMessage, arrayedKey)
op.sig = utils.base64.encode(signature)
Expand Down
6 changes: 3 additions & 3 deletions vue-app/src/api/claims.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Contract, FixedNumber } from 'ethers'
import { Contract, BigNumber } from 'ethers'
import sdk from '@/graphql/sdk'

import { FundingRound } from './abi'
Expand All @@ -9,10 +9,10 @@ export async function getAllocatedAmount(
tokenDecimals: number,
result: string,
spent: string,
): Promise<FixedNumber> {
): Promise<BigNumber> {
const fundingRound = new Contract(fundingRoundAddress, FundingRound, provider)
const allocatedAmount = await fundingRound.getAllocatedAmount(result, spent)
return FixedNumber.fromValue(allocatedAmount, tokenDecimals)
return allocatedAmount
}

export async function isFundsClaimed(
Expand Down
6 changes: 5 additions & 1 deletion vue-app/src/api/contributions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,11 @@ export async function getContributorIndex(fundingRoundAddress: string, pubKey: P
publicKeyId: id,
})

return data.publicKey?.stateIndex ? Number(data.publicKey.stateIndex) : null
if (data.publicKeys.length === 0) {
return null
}

return Number(data.publicKeys[0].stateIndex)
}

/**
Expand Down
26 changes: 23 additions & 3 deletions vue-app/src/api/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { ethers } from 'ethers'
import { FundingRoundFactory } from './abi'
import { CHAIN_INFO } from '@/utils/chains'

import historicalRounds from '@/rounds/rounds.json'
import { DateTime } from 'luxon'

export const rpcUrl = import.meta.env.VITE_ETHEREUM_API_URL
if (!rpcUrl) {
throw new Error('Please provide ethereum rpc url for connecting to blockchain')
Expand Down Expand Up @@ -48,9 +51,6 @@ if (!['simple', 'optimistic', 'kleros'].includes(recipientRegistryType as string
}
export const recipientRegistryPolicy = import.meta.env.VITE_RECIPIENT_REGISTRY_POLICY
export const operator: string = import.meta.env.VITE_OPERATOR || 'Clr.fund'
export const extraRounds: string[] = import.meta.env.VITE_EXTRA_ROUNDS
? import.meta.env.VITE_EXTRA_ROUNDS.split(',')
: []

export const SUBGRAPH_ENDPOINT =
import.meta.env.VITE_SUBGRAPH_URL || 'https://api.thegraph.com/subgraphs/name/clrfund/clrfund'
Expand All @@ -74,3 +74,23 @@ export const brightIdSponsorUrl = import.meta.env.VITE_BRIGHTID_SPONSOR_API_URL

// wait for data to sync with the subgraph
export const MAX_WAIT_DEPTH = Number(import.meta.env.VITE_MAX_WAIT_DEPTH) || 15

export type LeaderboardRound = {
address: string
network: string
}

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'

// Try to get the next scheduled start date
const nextStartDate = import.meta.env.VITE_NEXT_ROUND_START_DATE
? DateTime.fromFormat(import.meta.env.VITE_NEXT_ROUND_START_DATE, 'yyyy-MM-dd')
: null

export const nextRoundStartDate = nextStartDate?.isValid ? nextStartDate : null
Loading

0 comments on commit c2d9ced

Please sign in to comment.