Skip to content

Commit af2cd6c

Browse files
committed
Merge branch 'main' into fix-create-dao-address-validaton
2 parents 2843879 + 09d2ff0 commit af2cd6c

File tree

10 files changed

+553
-184
lines changed

10 files changed

+553
-184
lines changed
Lines changed: 11 additions & 0 deletions
Loading

apps/web/src/components/Icon/icons.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import External from './assets/external-16.svg'
2222
import Github from './assets/github.svg'
2323
import Globe from './assets/globe.svg'
2424
import HandlebarCircle from './assets/handlebar-circle.svg'
25+
import Info16 from './assets/info-16.svg'
2526
import Move from './assets/move.svg'
2627
import NewWindow from './assets/new-window.svg'
2728
import NounsConnect from './assets/nouns-connect.svg'
@@ -56,6 +57,7 @@ export const icons = {
5657
github: Github,
5758
eth: Eth,
5859
handlebarCircle: HandlebarCircle,
60+
'info-16': Info16,
5961
globe: Globe,
6062
move: Move,
6163
newWindow: NewWindow,

apps/web/src/modules/create-dao/components/AllocationForm/AllocationForm.schema.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const validateAddress = async (
1717

1818
export const deboucedValidateAddress = debounce(validateAddress, 500)
1919

20-
const allocationSchema = Yup.object().shape({
20+
export const allocationSchema = Yup.object().shape({
2121
founderAddress: Yup.string()
2222
.test(
2323
'isValidAddress',
@@ -28,12 +28,12 @@ const allocationSchema = Yup.object().shape({
2828
allocationPercentage: Yup.number()
2929
.transform((value) => (isNaN(value) ? undefined : value))
3030
.required('*')
31+
.integer('Must be whole number')
32+
.max(100, '< 100')
3133
.when('admin', (admin, schema) => {
3234
if (!admin) return schema.min(1, '> 0') // (condition, errorMessage) - allocation represented as % must be greater than or equal to 0
3335
return schema
34-
})
35-
.max(100, '< 100')
36-
.integer('Must be whole number'),
36+
}),
3737
endDate: Yup.string()
3838
.required('*')
3939
.test('isDateInFuture', 'Must be in future', (value: string | undefined) => {

apps/web/src/modules/dao/components/About/About.tsx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Box, Flex, Text } from '@zoralabs/zord'
1+
import { Box, Flex, Grid, Text } from '@zoralabs/zord'
22
import HtmlReactParser from 'html-react-parser'
33
import { getFetchableUrl } from 'ipfs-service'
44
import Image from 'next/legacy/image'
@@ -11,19 +11,22 @@ import { CHAIN } from 'src/constants/network'
1111
import SWR_KEYS from 'src/constants/swrKeys'
1212
import { metadataAbi, tokenAbi } from 'src/data/contract/abis'
1313
import { sdk } from 'src/data/graphql/client'
14+
import { useLayoutStore } from 'src/stores'
1415
import { about, daoDescription, daoInfo, daoName } from 'src/styles/About.css'
1516
import { unpackOptionalArray } from 'src/utils/helpers'
1617
import { formatCryptoVal } from 'src/utils/numbers'
1718

1819
import { useDaoStore } from '../../stores'
1920
import { parseContractURI } from '../../utils'
2021
import { ExternalLinks } from './ExternalLinks'
22+
import { Founder } from './Founder'
2123
import { Statistic } from './Statistic'
2224

2325
export const About: React.FC = () => {
2426
const {
2527
addresses: { token, treasury, metadata },
2628
} = useDaoStore()
29+
const { isMobile } = useLayoutStore()
2730

2831
const tokenContractParams = {
2932
abi: tokenAbi,
@@ -38,16 +41,15 @@ export const About: React.FC = () => {
3841
contracts: [
3942
{ ...tokenContractParams, functionName: 'name' },
4043
{ ...tokenContractParams, functionName: 'totalSupply' },
44+
{ ...tokenContractParams, functionName: 'getFounders' },
4145
{ ...metadataContractParams, functionName: 'contractImage' },
4246
{ ...metadataContractParams, functionName: 'description' },
4347
{ ...metadataContractParams, functionName: 'contractURI' },
4448
],
4549
})
4650

47-
const [name, totalSupply, daoImage, description, contractURI] = unpackOptionalArray(
48-
contractData,
49-
5
50-
)
51+
const [name, totalSupply, founders, daoImage, description, contractURI] =
52+
unpackOptionalArray(contractData, 6)
5153
const parsedContractURI = parseContractURI(contractURI)
5254

5355
const { data: balance } = useBalance({ address: treasury as Address })
@@ -133,6 +135,19 @@ export const About: React.FC = () => {
133135
>
134136
<ExternalLinks links={{ website: parsedContractURI?.external_url }} />
135137
</Box>
138+
139+
{typeof founders !== 'undefined' && founders.length > 0 ? (
140+
<>
141+
<Text variant="heading-xs" mt="x16" style={{ fontWeight: 800 }}>
142+
Founders
143+
</Text>
144+
<Grid columns={isMobile ? 1 : 2} mt="x6" gap="x4">
145+
{founders.map((founder) => (
146+
<Founder {...founder} />
147+
))}
148+
</Grid>
149+
</>
150+
) : null}
136151
</Box>
137152
)
138153
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { Box, Flex, PopUp, Text } from '@zoralabs/zord'
2+
import { useState } from 'react'
3+
4+
import { Avatar } from 'src/components/Avatar'
5+
import { Icon } from 'src/components/Icon'
6+
import { ETHERSCAN_BASE_URL } from 'src/constants/etherscan'
7+
import { useEnsData } from 'src/hooks'
8+
import { AddressType } from 'src/typings'
9+
10+
interface FounderProps {
11+
wallet: AddressType
12+
ownershipPct: number
13+
vestExpiry: number
14+
}
15+
16+
export const Founder: React.FC<FounderProps> = ({ wallet, ownershipPct, vestExpiry }) => {
17+
const [showTooltip, setShowTooltip] = useState(false)
18+
const { displayName, ensAvatar } = useEnsData(wallet as string)
19+
const vestDate = new Date(vestExpiry * 1000).toLocaleDateString(undefined, {
20+
year: 'numeric',
21+
month: 'short',
22+
day: 'numeric',
23+
})
24+
return (
25+
<Flex
26+
direction={'row'}
27+
align={'center'}
28+
justify={'space-between'}
29+
w={'100%'}
30+
borderStyle="solid"
31+
borderColor="border"
32+
borderWidth="normal"
33+
borderRadius="curved"
34+
p="x4"
35+
px="x6"
36+
>
37+
<Flex direction={'row'} align={'center'}>
38+
<Avatar address={wallet} src={ensAvatar} size={'40'} />
39+
<Flex direction={'column'} ml={'x2'}>
40+
<Text
41+
as="a"
42+
target="_blank"
43+
rel="noreferrer noopener"
44+
href={`${ETHERSCAN_BASE_URL}/address/${wallet}`}
45+
fontWeight={'display'}
46+
>
47+
{displayName}
48+
</Text>
49+
</Flex>
50+
</Flex>
51+
<Flex align={'center'} justify="center">
52+
<Text fontWeight={'display'} mr="x2">
53+
{ownershipPct}%
54+
</Text>
55+
<Box
56+
cursor="pointer"
57+
style={{ zIndex: 102 }}
58+
onMouseOver={() => setShowTooltip(true)}
59+
onMouseLeave={() => setShowTooltip(false)}
60+
>
61+
<Icon id="info-16" size="sm" />
62+
</Box>
63+
<PopUp open={showTooltip} trigger={<></>}>
64+
<Box>{`In effect until ${vestDate}`}</Box>
65+
</PopUp>
66+
</Flex>
67+
</Flex>
68+
)
69+
}

apps/web/src/modules/dao/components/AdminForm/AdminForm.schema.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { Provider } from '@ethersproject/abstract-provider'
22
import * as Yup from 'yup'
33

4-
import { auctionSettingsValidationSchema } from 'src/modules/create-dao'
4+
import { TokenAllocation, auctionSettingsValidationSchema } from 'src/modules/create-dao'
5+
import { allocationSchema } from 'src/modules/create-dao/components/AllocationForm/AllocationForm.schema'
56
import { Duration } from 'src/typings'
67
import { isValidAddress } from 'src/utils/ens'
78
import { durationValidationSchema, urlValidationSchema } from 'src/utils/yup'
@@ -17,6 +18,7 @@ export interface AdminFormValues {
1718
quorumThreshold: number
1819
votingPeriod: Duration
1920
votingDelay: Duration
21+
founderAllocation: TokenAllocation[]
2022
vetoPower: boolean
2123
vetoer: string
2224
}
@@ -48,6 +50,16 @@ export const adminValidationSchema = (provider: Provider | undefined) =>
4850
{ value: tenMinutes, description: '10 minutes' },
4951
{ value: twentyFourWeeks, description: '24 weeks' }
5052
),
53+
founderAllocation: Yup.array()
54+
.of(allocationSchema)
55+
.test(
56+
'unique',
57+
'Founder allocation addresses should be unique.',
58+
function (values) {
59+
const addresses = values?.map((v) => v.founderAddress)
60+
return values?.length === new Set(addresses)?.size
61+
}
62+
),
5163
vetoPower: Yup.bool().required('*'),
5264
})
5365
)

0 commit comments

Comments
 (0)