Skip to content

Commit

Permalink
Merge pull request sushiswap#107 from sushiswap/faucet
Browse files Browse the repository at this point in the history
[WIP] Implement Faucet Interface
  • Loading branch information
omakasebar authored May 19, 2021
2 parents f64ee17 dc067b1 commit 98d1500
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 1 deletion.
13 changes: 13 additions & 0 deletions src/components/AppBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 8,7 @@ import { ReactComponent as Burger } from '../assets/images/burger.svg'
import { ReactComponent as X } from '../assets/images/x.svg'
import Web3Network from './Web3Network'
import Web3Status from './Web3Status'
import Web3Faucet from './Web3Faucet'
import MoreMenu from './Menu'
import { ExternalLink, NavLink } from './Link'
import { Disclosure } from '@headlessui/react'
Expand Down Expand Up @@ -284,6 285,18 @@ function AppBar(): JSX.Element {
<Web3Status />
</div>
<LanguageSwitch />

{
chainId && [
ChainId.GÖRLI,
ChainId.KOVAN,
ChainId.RINKEBY,
ChainId.ROPSTEN
].includes(chainId) && (
<Web3Faucet />
)
}

<MoreMenu />
</div>
</div>
Expand Down
157 changes: 157 additions & 0 deletions src/components/FaucetModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 1,157 @@
import React, { useCallback, useContext, useEffect, useState } from 'react'
import styled, { ThemeContext } from 'styled-components'
import { ReactComponent as Close } from '../../assets/images/x.svg'
import { useFaucetContract } from '../../hooks/useContract'
import { ApplicationModal } from '../../state/application/actions'
import { useModalOpen, useFaucetModalToggle } from '../../state/application/hooks'
import { TYPE } from '../../theme'
import Modal from '../Modal'
import TransactionConfirmationModal, { TransactionErrorContent } from '../TransactionConfirmationModal'

const Wrapper = styled.div`
${({ theme }) => theme.flexColumnNoWrap}
margin: 0;
padding: 0;
width: 100%;
`

const HeaderRow = styled.div`
${({ theme }) => theme.flexRowNoWrap};
padding: 1rem 1rem;
font-weight: 500;
color: ${props => (props.color === 'blue' ? ({ theme }) => theme.primary1 : 'inherit')};
${({ theme }) => theme.mediaWidth.upToMedium`
padding: 1rem;
`};
`

const UpperSection = styled.div`
position: relative;
h5 {
margin: 0;
margin-bottom: 0.5rem;
font-size: 1rem;
font-weight: 400;
}
h5:last-child {
margin-bottom: 0px;
}
h4 {
margin-top: 0;
font-weight: 500;
}
`

const CloseIcon = styled.div`
position: absolute;
right: 1rem;
top: 14px;
&:hover {
cursor: pointer;
opacity: 0.6;
}
`

const CloseColor = styled(Close)`
path {
stroke: ${({ theme }) => theme.text4};
`

const LowerSection = styled.div`
${({ theme }) => theme.flexColumnNoWrap}
padding: 1.5rem;
flex-grow: 1;
overflow: auto;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
h5 {
margin: 0;
font-weight: 400;
color: ${({ theme }) => theme.text3};
}
`

export default function FaucetModal() {
const theme = useContext(ThemeContext)

const faucetModalOpen = useModalOpen(ApplicationModal.FAUCET)
const toggleFaucetModal = useFaucetModalToggle()
const faucetContract = useFaucetContract(true)

const [isRunning, setRunning] = useState(false)
const [isWaiting, setWaiting] = useState(false)
const [faucetErrorMessage, setError] = useState('')
const [txHash, setTxHash] = useState('')

const claimFaucet = useCallback(() => {
setRunning(true)
setWaiting(true)
setError('')
setTxHash('')
faucetContract?.drip()
.then((tx: any) => {
setWaiting(false)
setTxHash(tx.hash)
})
.catch((err: any) => {
if (err.code === 4001) {
setError('Transaction rejected.')
} else {
console.error(`Claim failed`, err, 'drip')
setError(`Claim failed: ${err.message}`)
}
setWaiting(false)
})
}, [faucetContract])

useEffect(() => {
if(faucetModalOpen) {
setRunning(false)
}
}, [faucetModalOpen])

function getModalContent() {
return (
<UpperSection>
<CloseIcon onClick={toggleFaucetModal}>
<CloseColor />
</CloseIcon>
<HeaderRow>Faucet</HeaderRow>
<LowerSection>
<TYPE.body color={theme.text1}>Claim your test tokens here...</TYPE.body>
<button
onClick={claimFaucet}
className="flex items-center bg-dark-800 hover:bg-dark-700 w-full rounded p-3 cursor-pointer mt-5"
>
<div className="text-primary font-bold text-center w-full">Claim</div>
</button>
</LowerSection>
</UpperSection>
)
}

const confirmationContent = useCallback(
() => <TransactionErrorContent onDismiss={toggleFaucetModal} message={faucetErrorMessage} />,
[toggleFaucetModal, faucetErrorMessage]
)

return (
!isRunning ?
<Modal isOpen={faucetModalOpen} onDismiss={toggleFaucetModal} minHeight={false} maxHeight={90}>
<Wrapper>{getModalContent()}</Wrapper>
</Modal>
:
<TransactionConfirmationModal
isOpen={faucetModalOpen}
onDismiss={toggleFaucetModal}
attemptingTxn={isWaiting}
hash={txHash}
content={confirmationContent}
pendingText={'Claiming test tokens'}
/>
)
}
26 changes: 26 additions & 0 deletions src/components/Web3Faucet/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 1,26 @@
import React from 'react'
import { useActiveWeb3React } from 'hooks/useActiveWeb3React'
import { useFaucetModalToggle } from '../../state/application/hooks'
import FaucetModal from '../FaucetModal'

function Web3Faucet(): JSX.Element | null {
const { chainId } = useActiveWeb3React()

const toggleFaucetModal = useFaucetModalToggle()

if (!chainId) return null

return (
<div
className="flex items-center rounded bg-dark-900 hover:bg-dark-800 p-0.5 whitespace-nowrap text-sm font-bold cursor-pointer select-none pointer-events-auto"
onClick={() => toggleFaucetModal()}
>
<div className="grid grid-flow-col auto-cols-max items-center rounded-lg bg-dark-1000 text-sm text-secondary py-2 px-3 pointer-events-auto text-primary">
Claim Test Tokens
</div>
<FaucetModal />
</div>
)
}

export default Web3Faucet
5 changes: 5 additions & 0 deletions src/constants/abis/faucet.ts
Original file line number Diff line number Diff line change
@@ -0,0 1,5 @@
import FAUCET_ABI from './faucet.json'

const FAUCET_ADDRESS = '0x5546e0295c7bb85b2fC00883B6025BA0Db06e50A'

export { FAUCET_ADDRESS, FAUCET_ABI }
5 changes: 5 additions & 0 deletions src/hooks/useContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 56,7 @@ import SUSHI_ABI from '../constants/abis/sushi.json'
import BASE_SWAPPER_ABI from '../constants/abis/swapper.json'
import TIMELOCK_ABI from '../constants/abis/timelock.json'
import SUSHISWAP_MULTISWAPPER_ABI from '../constants/abis/sushiswapmultiswapper.json'
import { FAUCET_ABI, FAUCET_ADDRESS } from '../constants/abis/faucet'
import { V1_EXCHANGE_ABI, V1_FACTORY_ABI, V1_FACTORY_ADDRESSES } from '../constants/v1'
import { getContract } from '../utils'
import { useActiveWeb3React } from './useActiveWeb3React'
Expand Down Expand Up @@ -534,3 535,7 @@ export function useQuickSwapFactoryContract(): Contract | null {
false
)
}

export function useFaucetContract(withSignerIfPossible?: boolean): Contract | null {
return useContract(FAUCET_ADDRESS, FAUCET_ABI, withSignerIfPossible)
}
3 changes: 2 additions & 1 deletion src/state/application/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 28,8 @@ export enum ApplicationModal {
DELEGATE,
VOTE,
LANGUAGE,
NETWORK
NETWORK,
FAUCET
}

export const updateBlockNumber = createAction<{ chainId: number; blockNumber: number }>('application/updateBlockNumber')
Expand Down
4 changes: 4 additions & 0 deletions src/state/application/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 63,10 @@ export function useToggleVoteModal(): () => void {
return useToggleModal(ApplicationModal.VOTE)
}

export function useFaucetModalToggle(): () => void {
return useToggleModal(ApplicationModal.FAUCET)
}

// returns a function that allows adding a popup
export function useAddPopup(): (content: PopupContent, key?: string) => void {
const dispatch = useDispatch()
Expand Down

0 comments on commit 98d1500

Please sign in to comment.