From ef53fb3582ccfd2caa1222a2be82d1af281f23df Mon Sep 17 00:00:00 2001 From: wilfred Date: Wed, 31 Jan 2024 10:20:42 +0700 Subject: [PATCH 1/2] fixed airdrop --- src/Providers/StoreProvider/index.tsx | 13 +- src/modules/airdrop/Section_2/index.tsx | 119 ----------- .../airdrop/StepAirdrop/Step/index.tsx | 185 ++++++++---------- src/modules/airdrop/StepAirdrop/index.tsx | 44 +++-- src/stores/index.ts | 2 +- src/stores/reducer.ts | 4 +- src/stores/states/airdrop/reducer.ts | 32 +++ src/stores/states/airdrop/types.ts | 12 ++ 8 files changed, 170 insertions(+), 241 deletions(-) create mode 100644 src/stores/states/airdrop/reducer.ts create mode 100644 src/stores/states/airdrop/types.ts diff --git a/src/Providers/StoreProvider/index.tsx b/src/Providers/StoreProvider/index.tsx index fe0742f79..eb3f58eff 100644 --- a/src/Providers/StoreProvider/index.tsx +++ b/src/Providers/StoreProvider/index.tsx @@ -1,8 +1,11 @@ 'use client'; -import { AppStore, store } from '@/stores'; +import AppLoading from '@/components/AppLoading'; +import { AppStore, persistor, store } from '@/stores'; +import { Center } from '@chakra-ui/react'; import React, { useRef } from 'react'; import { Provider } from 'react-redux'; +import { PersistGate } from 'redux-persist/integration/react'; // import useBootstrapApp from '@/hooks/useBootstrapApp'; @@ -18,5 +21,11 @@ export default function StoreProvider({ storeRef.current = store; } - return {children}; + return ( + + } persistor={persistor}> + {children} + + + ); } diff --git a/src/modules/airdrop/Section_2/index.tsx b/src/modules/airdrop/Section_2/index.tsx index 3a075bcd6..c09fd55b5 100644 --- a/src/modules/airdrop/Section_2/index.tsx +++ b/src/modules/airdrop/Section_2/index.tsx @@ -105,125 +105,6 @@ const Section_2 = () => { } }; - const renderItem = (item: IContent, index: number) => { - return ( - - {/* Date */} - - {item.dateStr} - - - {/* Content */} - - {/* ThumbImg */} - - - {/* Right - Content */} - - - {item.twitterLink && ( - - - - {item.appName} - - - )} - - - - - {item.linkShortName} - - - - - - - {item.title} - - - - {item.desc} - - - - - - - - - - ); - }; - return ( void; + loading?: boolean; } export default function ItemCommunity({ @@ -66,14 +66,14 @@ export default function ItemCommunity({ content, isLoading, onClickTweetToClaim, + loading, }: { index: number; content: IItemCommunity; isLoading?: boolean; onClickTweetToClaim: (airdropType: AirdropStep) => void; + loading?: boolean; }) { - console.log('content', content); - const [isEnd, setIsEnd] = React.useState( dayjs .utc(content?.expiredTime, 'YYYY-MM-DD HH:mm:ss') @@ -81,13 +81,13 @@ export default function ItemCommunity({ ); const { isActive, image, isDisable = false, step } = content; const airdropAlphaUsers = useSelector(airdropAlphaUsersSelector); - const airdropGMHolders = AirdropStorage.getAirdropGMHolders(); - const airdropGenerativeUsers = AirdropStorage.getAirdropGenerativeUsers(); - const airdropPerceptronsHolders = - AirdropStorage.getAirdropPerceptronsHolders(); const user = useAppSelector(userSelector); - const isConnectMetaMask = AirdropStorage.getIsConnectMetaMask(); - const isConnectBitcoinWallet = AirdropStorage.getIsConnectBitcoinWallet(); + + const airdrops = useSelector(airdropSelector).airdrops; + + const airdropContent = useMemo(() => { + return airdrops.find((v) => compareString(v.type, content.step)); + }, [airdrops, content]); const isRunning = useMemo(() => { return isActive; @@ -190,7 +190,7 @@ export default function ItemCommunity({ */} - + {airdropContent && !loading ? ( + <> + {airdropContent?.balance ? ( + + + Airdrop: {formatCurrency(airdropContent?.balance)}{' '} + $BVM - Vesting at:{' '} + {dayjs(airdropContent?.claimeable_at).format( + 'MMM D, YYYY', + )} + + + ) : ( + + Your wallet do not have airdrop + + )} + ) : ( - isConnectMetaMask && ( - - Your wallet do not have airdrop - - ) + <> )} )} {content?.step === AirdropStep.generativeUsers && ( <> - {airdropGenerativeUsers ? ( - - - Airdrop: {formatCurrency(airdropGenerativeUsers?.balance)}{' '} - $BVM - Vesting at:{' '} - {dayjs(airdropGenerativeUsers?.claimeable_at).format( - 'MMM D, YYYY', - )} - - {/* */} - + {airdropContent && !loading ? ( + <> + {airdropContent?.balance ? ( + + + Airdrop: {formatCurrency(airdropContent?.balance)}{' '} + $BVM - Vesting at:{' '} + {dayjs(airdropContent?.claimeable_at).format( + 'MMM D, YYYY', + )} + + + ) : ( + + Your wallet do not have airdrop + + )} + ) : ( - isConnectMetaMask && ( - - Your wallet do not have airdrop - - ) + <> )} )} {content?.step === AirdropStep.perceptronsHolders && ( <> - {airdropPerceptronsHolders ? ( - - - Airdrop:{' '} - {formatCurrency(airdropPerceptronsHolders?.balance)} $BVM - - Vesting at:{' '} - {dayjs(airdropPerceptronsHolders?.claimeable_at).format( - 'MMM D, YYYY', - )} - - {/* */} - + {airdropContent && !loading ? ( + <> + {airdropContent?.balance ? ( + + + Airdrop: {formatCurrency(airdropContent?.balance)}{' '} + $BVM - Vesting at:{' '} + {dayjs(airdropContent?.claimeable_at).format( + 'MMM D, YYYY', + )} + + + ) : ( + + Your wallet do not have airdrop + + )} + ) : ( - (isConnectMetaMask || isConnectBitcoinWallet) && ( - - Your wallet do not have airdrop - - ) + <> )} )} diff --git a/src/modules/airdrop/StepAirdrop/index.tsx b/src/modules/airdrop/StepAirdrop/index.tsx index 49494d650..a80640244 100644 --- a/src/modules/airdrop/StepAirdrop/index.tsx +++ b/src/modules/airdrop/StepAirdrop/index.tsx @@ -22,10 +22,11 @@ import AllowListStorage from '@/utils/storage/allowlist.storage'; import AuthenStorage from '@/utils/storage/authen.storage'; import { Flex } from '@chakra-ui/react'; import React, { useEffect, useMemo, useRef, useState } from 'react'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import ItemStep, { AirdropStep, AirdropType, IItemCommunity } from './Step'; import s from './styles.module.scss'; import { compareString } from '@/utils/string'; +import { airdropSelector, setAirdrop } from '@/stores/states/airdrop/reducer'; export const getMessageEVM = (address: string) => { return `Verify you are the owner of the wallet ${address}`; @@ -49,6 +50,9 @@ const StepsAirdrop = (props: IProps) => { const [authenCode, setAuthenCode] = useState(); const [showManualCheck, setShowManualCheck] = useState(false); const [showConnectModal, setShowConnectModal] = useState(false); + const airdrops = useSelector(airdropSelector).airdrops; + const [loading, setLoading] = useState(false); + const [currentStep, setCurrentStep] = useState(-1); useEffect(() => { if (token) { @@ -143,27 +147,34 @@ const StepsAirdrop = (props: IProps) => { const handleVerifyWallet = async (type?: AirdropStep) => { try { + setCurrentStep(type); const { address } = await signMessage(getMessageEVM); + let currentAirdropContent = { type }; + + const airdropContent = airdrops.find((v) => compareString(v.type, type)); + + if (!airdropContent) { + dispatch(setAirdrop(currentAirdropContent)); + } + + setLoading(true); + const resGMHolders = await getBVMAirdrop({ - address: address, + address: '0xd558Ce757d610ea33fFeA371693e48df8eFC292E', }); - AirdropStorage.setIsConnectMetaMask(true); - if (compareString(type, AirdropStep.generativeUsers)) { - AirdropStorage.setAirdropGenerativeUsers(JSON.stringify(resGMHolders)); - } else if (compareString(type, AirdropStep.perceptronsHolders)) { - AirdropStorage.setAirdropPerceptronsHolders( - JSON.stringify(resGMHolders), - ); - } else { - AirdropStorage.setAirdropGMHolders(JSON.stringify(resGMHolders)); + if (resGMHolders && compareString(resGMHolders.type, type)) { + currentAirdropContent = { + ...currentAirdropContent, + ...resGMHolders, + }; + dispatch(setAirdrop(currentAirdropContent)); } - setTimeout(() => { - window.location.reload(); - }, 1000); } catch (error) { console.log('error', error); + } finally { + setLoading(false); } }; @@ -222,7 +233,7 @@ const StepsAirdrop = (props: IProps) => { `, actionText: 'Connect your Metamask', image: '/airdrop/gm.png', - actionHandle: handleVerifyWallet, + actionHandle: () => handleVerifyWallet(AirdropStep.gmHolders), isActive: true, isDisable: true, right: { @@ -259,7 +270,7 @@ const StepsAirdrop = (props: IProps) => { handleShowManualPopup: handleShowManualPopup, }, ]; - }, [token, needReload, raffleCode]); + }, [token, needReload, raffleCode, loading, currentStep]); return ( { content={item} isLoading={item.step === AirdropStep.alphaUsers && submitting} onClickTweetToClaim={handleTweetToClaim} + loading={loading && compareString(currentStep, item.step)} /> ); })} diff --git a/src/stores/index.ts b/src/stores/index.ts index 1b8803ffd..afee6af6e 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -10,7 +10,7 @@ const reducers = combineReducers(reducer); const persistConfig = getPersistConfig({ key: 'root', storage: persistLocalStorage, - whitelist: ['liquidity', 'futures', 'common.poolTabIndex', 'common.coinPrices'], + whitelist: ['common.poolTabIndex', 'common.coinPrices', 'airdrop'], rootReducer: reducers, }); diff --git a/src/stores/reducer.ts b/src/stores/reducer.ts index ac6065844..255b40754 100644 --- a/src/stores/reducer.ts +++ b/src/stores/reducer.ts @@ -3,10 +3,12 @@ import common from '@/stores/states/common/reducer'; import modal from '@/stores/states/modal/reducer'; import user from '@/stores/states/user/reducer'; import activities from '@/stores/states/activities/reducer'; +import airdrop from '@/stores/states/airdrop/reducer'; export default { common, modal, user, - activities + activities, + airdrop, }; diff --git a/src/stores/states/airdrop/reducer.ts b/src/stores/states/airdrop/reducer.ts new file mode 100644 index 000000000..7a199ac5b --- /dev/null +++ b/src/stores/states/airdrop/reducer.ts @@ -0,0 +1,32 @@ +import { createSlice } from '@reduxjs/toolkit'; +import { CommonState } from './types'; +import { RootState } from '@/stores'; +import { compareString } from '@/utils/string'; + +const initialState: CommonState = { + airdrops: [], +}; + +const slice = createSlice({ + name: 'airdrop', + initialState, + reducers: { + setAirdrop: (state, actions) => { + const airdrop = state.airdrops.findIndex((v) => + compareString(v.type, actions.payload?.type), + ); + + if (airdrop >= 0) { + state.airdrops[airdrop] = actions.payload; + } else { + state.airdrops = [...state.airdrops, actions.payload]; + } + }, + }, +}); + +export const { setAirdrop } = slice.actions; + +export const airdropSelector = (state: RootState) => state.airdrop; + +export default slice.reducer; diff --git a/src/stores/states/airdrop/types.ts b/src/stores/states/airdrop/types.ts new file mode 100644 index 000000000..f81d43c0f --- /dev/null +++ b/src/stores/states/airdrop/types.ts @@ -0,0 +1,12 @@ +interface IAirdrop { + id?: number; + address?: string; + balance?: string; + type?: number; + claimed?: boolean; + claimeable_at?: Date; +} + +export interface CommonState { + airdrops: IAirdrop[]; +} From d9af3fe1856a4aaa3c676e0197f2f79d8e9d3a69 Mon Sep 17 00:00:00 2001 From: wilfred Date: Wed, 31 Jan 2024 10:23:54 +0700 Subject: [PATCH 2/2] update --- src/modules/airdrop/StepAirdrop/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/airdrop/StepAirdrop/index.tsx b/src/modules/airdrop/StepAirdrop/index.tsx index a80640244..721463fb7 100644 --- a/src/modules/airdrop/StepAirdrop/index.tsx +++ b/src/modules/airdrop/StepAirdrop/index.tsx @@ -161,7 +161,7 @@ const StepsAirdrop = (props: IProps) => { setLoading(true); const resGMHolders = await getBVMAirdrop({ - address: '0xd558Ce757d610ea33fFeA371693e48df8eFC292E', + address, }); if (resGMHolders && compareString(resGMHolders.type, type)) {