Commit 5dce68a6 authored by aballerr's avatar aballerr Committed by GitHub

feat: Implementing claims logic, adding error state and minor copy change (#5357)

* Implementing claims logic
parent 9dd8ad1d
[
{
"inputs": [
{
"internalType": "address",
"name": "token_",
"type": "address"
},
{
"internalType": "bytes32",
"name": "merkleRoot_",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "endTime_",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "AlreadyClaimed",
"type": "error"
},
{
"inputs": [],
"name": "ClaimWindowFinished",
"type": "error"
},
{
"inputs": [],
"name": "EndTimeInPast",
"type": "error"
},
{
"inputs": [],
"name": "InvalidProof",
"type": "error"
},
{
"inputs": [],
"name": "NoWithdrawDuringClaim",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "index",
"type": "uint256"
},
{
"indexed": false,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "Claimed",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "index",
"type": "uint256"
},
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"internalType": "bytes32[]",
"name": "merkleProof",
"type": "bytes32[]"
}
],
"name": "claim",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "endTime",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "index",
"type": "uint256"
}
],
"name": "isClaimed",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "merkleRoot",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "token",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "withdraw",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
......@@ -11,7 +11,7 @@ import { ApplicationModal } from 'state/application/reducer'
const Bag = lazy(() => import('nft/components/bag/Bag'))
const TransactionCompleteModal = lazy(() => import('nft/components/collection/TransactionCompleteModal'))
const AirdropModal = lazy(() => import('components/AidropModal'))
const AirdropModal = lazy(() => import('components/AirdropModal'))
export default function TopLevelModals() {
const addressClaimOpen = useModalIsOpen(ApplicationModal.ADDRESS_CLAIM)
......
......@@ -9,6 +9,7 @@ import useCopyClipboard from 'hooks/useCopyClipboard'
import useStablecoinPrice from 'hooks/useStablecoinPrice'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
import { useProfilePageState, useSellAsset, useWalletCollections } from 'nft/hooks'
import { useIsNftClaimAvailable } from 'nft/hooks/useIsNftClaimAvailable'
import { ProfilePageStateType } from 'nft/types'
import { useCallback, useMemo } from 'react'
import { Copy, ExternalLink, Power } from 'react-feather'
......@@ -117,6 +118,7 @@ const AuthenticatedHeader = () => {
const setSellPageState = useProfilePageState((state) => state.setProfilePageState)
const resetSellAssets = useSellAsset((state) => state.reset)
const clearCollectionFilters = useWalletCollections((state) => state.clearCollectionFilters)
const isClaimAvailable = useIsNftClaimAvailable((state) => state.isClaimAvailable)
const unclaimedAmount: CurrencyAmount<Token> | undefined = useUserUnclaimedAmount(account)
const isUnclaimed = useUserHasAvailableClaim(account)
......@@ -187,7 +189,7 @@ const AuthenticatedHeader = () => {
<Trans>Claim</Trans> {unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} <Trans>reward</Trans>
</UNIButton>
)}
{nftFlag === NftVariant.Enabled && (
{nftFlag === NftVariant.Enabled && isClaimAvailable && (
<UNIButton size={ButtonSize.medium} emphasis={ButtonEmphasis.medium} onClick={openNftModal}>
<Trans>Claim Uniswap NFT Airdrop</Trans>
</UNIButton>
......
......@@ -7,6 +7,7 @@ import WalletDropdown from 'components/WalletDropdown'
import { getConnection } from 'connection/utils'
import { NftVariant, useNftFlag } from 'featureFlags/flags/nft'
import { Portal } from 'nft/components/common/Portal'
import { useIsNftClaimAvailable } from 'nft/hooks/useIsNftClaimAvailable'
import { getIsValidSwapQuote } from 'pages/Swap'
import { darken } from 'polished'
import { useMemo, useRef } from 'react'
......@@ -14,6 +15,7 @@ import { AlertTriangle, ChevronDown, ChevronUp } from 'react-feather'
import { useAppSelector } from 'state/hooks'
import { useDerivedSwapInfo } from 'state/swap/hooks'
import styled, { useTheme } from 'styled-components/macro'
import { colors } from 'theme/colors'
import { flexRowNoWrap } from 'theme/styles'
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
......@@ -95,11 +97,16 @@ const Web3StatusConnectWrapper = styled.div<{ faded?: boolean }>`
}
`
const Web3StatusConnected = styled(Web3StatusGeneric)<{ pending?: boolean; isNftActive?: boolean }>`
const Web3StatusConnected = styled(Web3StatusGeneric)<{
pending?: boolean
isNftActive?: boolean
isClaimAvailable?: boolean
}>`
background-color: ${({ pending, theme }) => (pending ? theme.deprecated_primary1 : theme.deprecated_bg1)};
border: 1px solid ${({ pending, theme }) => (pending ? theme.deprecated_primary1 : theme.deprecated_bg1)};
color: ${({ pending, theme }) => (pending ? theme.deprecated_white : theme.deprecated_text1)};
font-weight: 500;
border: ${({ isClaimAvailable }) => isClaimAvailable && `1px solid ${colors.purple300}`};
:hover,
:focus {
border: 1px solid ${({ theme }) => darken(0.05, theme.deprecated_bg3)};
......@@ -202,6 +209,7 @@ function Web3StatusInner() {
const toggleWalletDropdown = useToggleWalletDropdown()
const toggleWalletModal = useToggleWalletModal()
const walletIsOpen = useModalIsOpen(ApplicationModal.WALLET_DROPDOWN)
const isClaimAvailable = useIsNftClaimAvailable((state) => state.isClaimAvailable)
const error = useAppSelector((state) => state.connection.errorByConnectionType[getConnection(connector).type])
const isNftActive = useNftFlag() === NftVariant.Enabled
......@@ -241,6 +249,7 @@ function Web3StatusInner() {
isNftActive={isNftActive}
onClick={toggleWallet}
pending={hasPendingTransactions}
isClaimAvailable={isClaimAvailable}
>
{!hasPendingTransactions && <StatusIcon size={24} connectionType={connectionType} />}
{hasPendingTransactions ? (
......
......@@ -8,6 +8,8 @@ type AddressMap = { [chainId: number]: string }
export const UNI_ADDRESS: AddressMap = constructSameAddressMap('0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984')
export const UNISWAP_NFT_AIRDROP_CLAIM_ADDRESS = '0x8B799381ac40b838BBA4131ffB26197C432AFe78'
export const V2_FACTORY_ADDRESSES: AddressMap = constructSameAddressMap(V2_FACTORY_ADDRESS)
export const V2_ROUTER_ADDRESS: AddressMap = constructSameAddressMap('0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D')
......
import create from 'zustand'
import { devtools } from 'zustand/middleware'
interface NFTClaim {
isClaimAvailable: boolean
setIsClaimAvailable: (isClaimAvailable: boolean) => void
}
export const useIsNftClaimAvailable = create<NFTClaim>()(
devtools(
(set) => ({
isClaimAvailable: false,
setIsClaimAvailable: (isClaimAvailable: boolean) => {
set(() => ({ isClaimAvailable }))
},
}),
{ name: 'useIsNftClaimAvailable' }
)
)
import { Rewards } from 'nft/types/airdrop'
interface CollectionrRewardsResponse {
data: Array<Rewards>
}
export const CollectionRewardsFetcher = async (address: string): Promise<CollectionrRewardsResponse> => {
const url = `${process.env.REACT_APP_TEMP_API_URL}/nft/rewards/${address}?category=GENIE_UNISWAP_USDC_AIRDROP`
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), 3000)
const r = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
clearInterval(timeoutId)
const data = await r.json()
return data
}
export enum Airdrop {
LOOKS_RARE_NFT_COMMERCE_REWARDS = 'LOOKS_RARE_NFT_COMMERCE_REWARDS',
GENIE_UNISWAP_USDC_AIRDROP = 'GENIE_UNISWAP_USDC_AIRDROP',
}
export interface Rewards {
amount: string
walletAddress: string
tokenAddress: string
merkleProof: Array<string>
rewardType: Airdrop
chainId: number
index: number
}
......@@ -83,6 +83,7 @@ export const colors = {
blueVibrant: '#587BFF',
// TODO: add magenta 50-900
magentaVibrant: '#FC72FF',
purple300: '#8440F2',
purple900: '#1C0337',
// TODO: add all other vibrant variations
networkEthereum: '#627EEA',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment