Skip to content

Commit

Permalink
Merge pull request #69 from linkpoolio/feature/add-new-features
Browse files Browse the repository at this point in the history
feat: New features
  • Loading branch information
1marcghannam authored May 26, 2023
2 parents 4aa12ef + a1b6a9c commit f13e58c
Show file tree
Hide file tree
Showing 18 changed files with 255 additions and 104 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export ANVIL_PRIVATE_KEY="" # Get from anvil after running for the first time, s

# UI
export UI_RAFFLE_MANAGER_CONTRACT_ADDRESS= # Get from anvil after deploying contract
export UI_LINK_TOKEN_CONTRACT_ADDRESS=
export UI_LINK_TOKEN_CONTRACT_ADDRESS=
export UI_KEEPER_REGISTRY_CONTRACT_ADDRESS=
```

### 4. Setup Wallet
Expand All @@ -62,7 +63,7 @@ $ docker compose up

### 1. Setup Foundry

([Installation instructions](https://book.getfoundry.sh/getting-started/installation)
[Installation instructions](https://book.getfoundry.sh/getting-started/installation)

```bash
# Download foundry
Expand Down
2 changes: 1 addition & 1 deletion client/packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"react-test-renderer": "^18.2.0",
"string.prototype.replaceall": "^1.0.7",
"ts-jest": "^29.0.5",
"typescript": "4.9.5",
"typescript": "^4.9.5",
"vite": "^2.5.4",
"vite-plugin-react-md": "^1.0.1"
}
Expand Down
4 changes: 3 additions & 1 deletion client/packages/ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Routes } from '@ui/Routes'
import { RaffleList } from '@ui/features/raffleList'
import { RaffleDetail } from '@ui/features/raffleDetail'
import { RaffleCreate } from '@ui/features/raffleCreate'
import { AuthenticatedRoute, Hero } from '@ui/components'
import { AuthenticatedRoute, Hero, FAQ } from '@ui/components'

export const App = () => (
<>
Expand All @@ -26,6 +26,8 @@ export const App = () => (
render={({ match }) => <RaffleDetail id={match.params.id} />}
/>

<Route path={Routes.FAQ} render={FAQ} />

<Route exact path={Routes.RaffleCreate}>
<AuthenticatedRoute connected={true}>
<RaffleCreate />
Expand Down
3 changes: 2 additions & 1 deletion client/packages/ui/src/Routes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export const Routes = {
RaffleList: '/',
RaffleDetail: '/raffle/:id',
RaffleCreate: '/create'
RaffleCreate: '/create',
FAQ: '/faq'
}

export const createRoute = ({ route, id }) => route.replace(':id', id)
24 changes: 23 additions & 1 deletion client/packages/ui/src/api/contracts/readFunctions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { readContract } from '@wagmi/core'

import { useEffect } from 'react'
import { useContractRead } from 'wagmi'
import { env } from '@ui/config'
import {
transformRaffleItem,
Expand Down Expand Up @@ -42,6 +43,27 @@ export const getRaffle = async (id: number): Promise<RaffleInstance> => {
}
}

export const getRaffleHook = (store, id) => {
const { data, isError, isLoading, isSuccess } = useContractRead({
...defaultOptions,
address: raffleManagerContractAddress,
functionName: 'getRaffle',
args: [id]
})
useEffect(() => {
if (!id || !isSuccess) return
const transformedData = transformRaffleItem(data)
if (
data &&
JSON.stringify(store.state.raffle) !== JSON.stringify(transformedData)
) {
store.update({ raffle: transformedData })
}
}, [data, store, id, isSuccess])

return { data, isError, isLoading, isSuccess }
}

export const getClaimableLink = async (id: number): Promise<number> => {
try {
const data = await readContract({
Expand Down
61 changes: 61 additions & 0 deletions client/packages/ui/src/components/faq/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React from 'react'
import {
Container,
Heading,
Text,
Divider,
Box,
VStack
} from '@chakra-ui/react'

const faqList = [
{
question: 'What is a Chainlink Raffle?',
answer:
"A Chainlink Raffle is a lottery system built on the blockchain. It uses Chainlink's Verifiable Random Function (VRF) to ensure that the selection of winners is provably fair and transparent."
},
{
question: 'How do I participate in a Chainlink Raffle?',
answer:
"To participate in a Chainlink Raffle, you first need to register or 'sign up' during the sign up period. Once the raffle event is committed on-chain, you become a participant and stand a chance to win prizes when the raffle is settled."
},
{
question: 'How are the winners selected?',
answer:
"Winners are selected using Chainlink's Verifiable Random Function (VRF). This is a trusted and secure source of randomness on the blockchain. It ensures that the winner selection process is fair, transparent, and tamper-proof."
},
{
question: 'What is the role of the raffle owner?',
answer:
'The raffle owner is responsible for creating and managing the raffle. They commit the rules of the raffle on-chain, such as the number of winners, the prizes, and the sign up period.'
},
{
question: 'What is the difference between Dynamic and Static Raffles?',
answer:
'Dynamic Raffles have a level of flexibility as they allow participants to enter at any point before the raffle ends, provided they meet the necessary conditions. This feature provides the potential for a larger participant pool over time. Static Raffles, however, have a predetermined set of participants at the outset of the raffle event. Once the raffle starts, no new entrants can participate. This creates a fixed and unchanging number of entries over time.'
}
]

export const FAQ = () => {
return (
<Container maxW="container.xl" mt="20" mb="20">
<Heading size="2xl" fontWeight="700" mb="6">
What are Chainlink Raffles?
</Heading>
<Text fontSize="lg" color="brand.gray_70" fontWeight="600">
Frequently Asked Questions
</Text>
<Divider orientation="horizontal" mt="16" mb="16" />
<VStack spacing={8} align="stretch">
{faqList.map((faq, index) => (
<Box key={index}>
<Heading size="lg" fontWeight="600">
{faq.question}
</Heading>
<Text mt={2}>{faq.answer}</Text>
</Box>
))}
</VStack>
</Container>
)
}
1 change: 1 addition & 0 deletions client/packages/ui/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from './pending'
export * from './success'
export * from './form'
export * from './icons'
export * from './faq'
14 changes: 14 additions & 0 deletions client/packages/ui/src/components/navigationBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,23 @@ export const NavigationBar = () => {
textTransform: 'none',
color: 'brand.primary'
}}
display={{ base: 'none', md: 'inline-flex' }}
href={Routes.RaffleList}>
Home
</Link>
<Link
as={RouterLink}
to={Routes.FAQ}
fontSize="sm"
color="brand.gray_70"
fontWeight={600}
_hover={{
textTransform: 'none',
color: 'brand.primary'
}}
href={Routes.FAQ}>
FAQ
</Link>
</Flex>
<Flex alignItems="center" justifyContent="space-between" gap="6">
{address && (
Expand Down
12 changes: 10 additions & 2 deletions client/packages/ui/src/features/raffleCreate/components/create.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react'
import { useHistory } from 'react-router-dom'
import { useAccount } from 'wagmi'
import { Link as RouterLink } from 'react-router-dom'
import {
Container,
Heading,
Expand All @@ -10,9 +11,9 @@ import {
Input,
Grid,
GridItem,
Button
Button,
Link
} from '@chakra-ui/react'

import { Routes } from '@ui/Routes'
import { Error, Control } from '@ui/components'
import { useAsyncManager, useStore } from '@ui/hooks'
Expand Down Expand Up @@ -132,6 +133,13 @@ export const RaffleCreate = () => {
<Text fontSize="lg" color="brand.gray_70" fontWeight="600">
Create dynamic or static raffle
</Text>
<Link
as={RouterLink}
to={Routes.FAQ}
color="brand.blue"
textDecoration="underline">
Need help? Check out our FAQ page.
</Link>
</Center>
<Grid templateColumns="repeat(3, 1fr)" gap={14} rowGap={14} mb={12}>
<GridItem>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react'
import { ethers } from 'ethers'
import { GridItem } from '@chakra-ui/react'

import { CSVUpload, Control } from '@ui/components'

export const initialStaticState = {
Expand All @@ -18,6 +17,18 @@ export const FormStatic = ({ update, validation }) => {
update({ participants })
}

const downloadCSV = () => {
const exampleCSV = 'john\nsteve\nbrad'
const blob = new Blob([exampleCSV], { type: 'text/csv' })
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = 'example.csv'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}

return (
<GridItem colSpan={2}>
<Control
Expand All @@ -26,7 +37,8 @@ export const FormStatic = ({ update, validation }) => {
errorMessage={validation['participants']}
helper={
<>
<button>Click here to download</button> CSV file example
<button onClick={downloadCSV}>Click here to download</button> CSV
file example
</>
}>
<CSVUpload
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React, { useState, useEffect } from 'react'
import { Button, Text, Stack, Flex, Heading } from '@chakra-ui/react'
import { Button, Text, Stack, Flex, Heading, Tooltip } from '@chakra-ui/react'

export const CheckWinners = ({ store, reset }) => {
const [winners, setWinners] = useState([])

const componentDidMount = () => {
readWinners(store)
}

useEffect(componentDidMount, [])

const readWinners = (store) => {
Expand All @@ -21,6 +23,16 @@ export const CheckWinners = ({ store, reset }) => {
setWinners(winnersArr)
}

const exportToCSV = () => {
const csvData = winners.join('\n')
const blob = new Blob([csvData], { type: 'text/csv' })
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.download = 'winners.csv'
link.href = url
link.click()
}

return (
<>
<Heading size="md" mb="6">
Expand All @@ -34,6 +46,16 @@ export const CheckWinners = ({ store, reset }) => {
))}
</Stack>
<Flex mt="2" justify="end">
<Tooltip
hasArrow
arrowSize={10}
placement="top"
color="red.500"
label="Warning: You are exporting private data.">
<Button variant="default" mr="4" onClick={exportToCSV}>
Export to CSV
</Button>
</Tooltip>
<Button variant="default" onClick={() => reset(store)}>
Close
</Button>
Expand Down
Loading

0 comments on commit f13e58c

Please sign in to comment.