From f1b2f3f13b0099803bdfb785c02acd90ef73beb3 Mon Sep 17 00:00:00 2001 From: Behnam Jaberi Date: Thu, 22 Jun 2023 18:27:44 +0330 Subject: [PATCH 01/11] Add wagmi component auth to projcet --- src/assets/images/tokens/arbitrum.svg | 9 ++ src/assets/images/tokens/celo.svg | 11 +++ src/assets/images/tokens/eth.png | Bin 0 -> 3954 bytes src/assets/images/tokens/polygon.svg | 16 ++++ src/components/AppHeader.js | 29 +++++- .../header/auth/AuthHeaderDropDown.js | 83 ++++++++++++++++++ src/components/header/auth/index.js | 3 + src/scss/_custom.scss | 7 ++ 8 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 src/assets/images/tokens/arbitrum.svg create mode 100644 src/assets/images/tokens/celo.svg create mode 100644 src/assets/images/tokens/eth.png create mode 100644 src/assets/images/tokens/polygon.svg create mode 100644 src/components/header/auth/AuthHeaderDropDown.js create mode 100644 src/components/header/auth/index.js diff --git a/src/assets/images/tokens/arbitrum.svg b/src/assets/images/tokens/arbitrum.svg new file mode 100644 index 000000000..d439bc6f6 --- /dev/null +++ b/src/assets/images/tokens/arbitrum.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/images/tokens/celo.svg b/src/assets/images/tokens/celo.svg new file mode 100644 index 000000000..bd24e97d7 --- /dev/null +++ b/src/assets/images/tokens/celo.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/src/assets/images/tokens/eth.png b/src/assets/images/tokens/eth.png new file mode 100644 index 0000000000000000000000000000000000000000..760946e76911accfd17cc84d84896c2ffab3b752 GIT binary patch literal 3954 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 M07*qoM6N<$f?!r`Q2+n{ literal 0 HcmV?d00001 diff --git a/src/assets/images/tokens/polygon.svg b/src/assets/images/tokens/polygon.svg new file mode 100644 index 000000000..a5bb6124f --- /dev/null +++ b/src/assets/images/tokens/polygon.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/src/components/AppHeader.js b/src/components/AppHeader.js index dd5f544e3..3d26dabb3 100644 --- a/src/components/AppHeader.js +++ b/src/components/AppHeader.js @@ -15,11 +15,28 @@ import CIcon from '@coreui/icons-react' import { cilBell, cilEnvelopeOpen, cilList, cilMenu } from '@coreui/icons' import { AppBreadcrumb } from './index' -import { AppHeaderDropdown } from './header/index' +import { AuthHeaderDropdown } from './header/auth/index' import { logo } from 'src/assets/brand/logo' +// Wagnumi Auth // +import { EthereumClient, w3mConnectors, w3mProvider } from '@web3modal/ethereum' +import { Web3Modal } from '@web3modal/react' +import { configureChains, createConfig, WagmiConfig } from 'wagmi' +import { arbitrum, mainnet, polygon } from 'wagmi/chains' + +const chains = [arbitrum, mainnet, polygon] +const projectId = 'YOUR_PROJECT_ID' + +const { publicClient } = configureChains(chains, [w3mProvider({ projectId })]) +const wagmiConfig = createConfig({ + autoConnect: true, + connectors: w3mConnectors({ projectId, version: 1, chains }), + publicClient +}) + const AppHeader = () => { const dispatch = useDispatch() + const ethereumClient = new EthereumClient(wagmiConfig, chains) const sidebarShow = useSelector((state) => state.sidebarShow) return ( @@ -47,6 +64,13 @@ const AppHeader = () => { Settings + + + + + + + @@ -64,9 +88,6 @@ const AppHeader = () => { - - - diff --git a/src/components/header/auth/AuthHeaderDropDown.js b/src/components/header/auth/AuthHeaderDropDown.js new file mode 100644 index 000000000..c27e31fb1 --- /dev/null +++ b/src/components/header/auth/AuthHeaderDropDown.js @@ -0,0 +1,83 @@ +import React from "react"; +import { useWeb3Modal } from '@web3modal/react' +import { useNetwork, useSwitchNetwork, useAccount } from 'wagmi' + +import { + CAvatar, + CBadge, + CButton, + CDropdown, + CDropdownMenu, + CDropdownItem, + CDropdownToggle +} from '@coreui/react' +import ethIcon from '../../../assets/images/tokens/eth.png' +import arbitIcon from '../../../assets/images/tokens/arbitrum.svg' +import maticIcon from '../../../assets/images/tokens/polygon.svg' + + + +const ConnectWalletButton = () => { + const { chain } = useNetwork() + const { open } = useWeb3Modal() + const { chains, isLoading, pendingChainId, switchNetwork } = useSwitchNetwork() + const { address, status } = useAccount() + const supportedNetwork = [ + { + "name": "Ethereum", + "cover": ethIcon + }, + { + "name": "Arbitrum One", + "cover": arbitIcon + }, { + "name": "Polygon", + "cover": maticIcon + } + ] + + const findToken = (name) => { + return supportedNetwork.find(x => x.name === name) + } + + return ( + <> +
+ open()} color="secondary" variant="outline" + className={address ? 'w-50 text-truncate h-75' : 'w-auto'}> + {address ? address : 'Connect Your Wallet'} + + {chain && + + + {findToken(chain.name) ? '' : 'Unsupported Network Choosen'} + + {findToken(chain.name) && + New alerts + } + + + {chains.map((x) => ( switchNetwork?.(x.id)} + > + + {x.name} + {isLoading && pendingChainId === x.id && ' (switching)'} + ) + )} + + } +
+ + ) +}; + +export default ConnectWalletButton; \ No newline at end of file diff --git a/src/components/header/auth/index.js b/src/components/header/auth/index.js new file mode 100644 index 000000000..fc48eaf49 --- /dev/null +++ b/src/components/header/auth/index.js @@ -0,0 +1,3 @@ +import AuthHeaderDropdown from './AuthHeaderDropDown' + +export { AuthHeaderDropdown } diff --git a/src/scss/_custom.scss b/src/scss/_custom.scss index 15d367af4..c53e63d02 100644 --- a/src/scss/_custom.scss +++ b/src/scss/_custom.scss @@ -1 +1,8 @@ // Here you can add other styles + + +// Size // +.w-15-icon { + width: 15px; + height: 15px; +} \ No newline at end of file From 52fc5803bc9872a2c7c4a0a83daf1a9ebebe5e92 Mon Sep 17 00:00:00 2001 From: Behnam Jaberi Date: Mon, 3 Jul 2023 17:55:36 +0330 Subject: [PATCH 02/11] Add wagmi react to projcet --- src/components/header/auth/WalletDropdown.js | 31 ++++++++++++++++++++ src/components/header/wagmi/index.js | 29 ++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/components/header/auth/WalletDropdown.js create mode 100644 src/components/header/wagmi/index.js diff --git a/src/components/header/auth/WalletDropdown.js b/src/components/header/auth/WalletDropdown.js new file mode 100644 index 000000000..12031c207 --- /dev/null +++ b/src/components/header/auth/WalletDropdown.js @@ -0,0 +1,31 @@ +import React from 'react'; +import { CAvatar, CBadge, CDropdown, CDropdownMenu, CDropdownItem, CDropdownToggle } from '@coreui/react'; + +const WalletDropdown = ({ address, open, signIn, visible, status }) => { + return ( + + {visible && ( + + New alerts + + )} + + + {address} + + {/* Dropdown Menu */} + + Account + Sign in wallet + + + ); +}; + +export default WalletDropdown; diff --git a/src/components/header/wagmi/index.js b/src/components/header/wagmi/index.js new file mode 100644 index 000000000..3245fbc2c --- /dev/null +++ b/src/components/header/wagmi/index.js @@ -0,0 +1,29 @@ +import React from 'react'; +import ConnectWalletButton from '../auth'; +import { EthereumClient, w3mConnectors, w3mProvider } from '@web3modal/ethereum'; +import { Web3Modal } from '@web3modal/react'; +import { configureChains, createConfig, WagmiConfig } from 'wagmi'; +import { arbitrum, mainnet, polygon } from 'wagmi/chains'; + +const chains = [arbitrum, mainnet, polygon]; +const projectId = 'Your Projcet ID'; + +const { publicClient } = configureChains(chains, [w3mProvider({ projectId })]); +const wagmiConfig = createConfig({ + autoConnect: true, + connectors: w3mConnectors({ projectId, version: 1, chains }), + publicClient +}); + +const ethereumClient = new EthereumClient(wagmiConfig, chains); + +const WagmiAuth = () => { + return ( + + + + + ); +}; + +export default WagmiAuth; From 0fac35e7fe4ba7f86b405baa4957695ee90605c3 Mon Sep 17 00:00:00 2001 From: Behnam Jaberi Date: Mon, 3 Jul 2023 17:56:07 +0330 Subject: [PATCH 03/11] Add supported network --- .../header/auth/SupportedNetwork.js | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/components/header/auth/SupportedNetwork.js diff --git a/src/components/header/auth/SupportedNetwork.js b/src/components/header/auth/SupportedNetwork.js new file mode 100644 index 000000000..9f17a65ed --- /dev/null +++ b/src/components/header/auth/SupportedNetwork.js @@ -0,0 +1,21 @@ +// supportedNetwork.js +import ethIcon from '../../../assets/images/tokens/eth.png'; +import arbitIcon from '../../../assets/images/tokens/arbitrum.svg'; +import maticIcon from '../../../assets/images/tokens/polygon.svg'; + +const supportedNetwork = [ + { + name: 'Ethereum', + cover: ethIcon, + }, + { + name: 'Arbitrum One', + cover: arbitIcon, + }, + { + name: 'Polygon', + cover: maticIcon, + }, +]; + +export default supportedNetwork; From 81998049964d835605c1780264955683cfa480fa Mon Sep 17 00:00:00 2001 From: Behnam Jaberi Date: Mon, 3 Jul 2023 17:56:29 +0330 Subject: [PATCH 04/11] Add chain component --- src/components/header/auth/ChainDropdown.js | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/components/header/auth/ChainDropdown.js diff --git a/src/components/header/auth/ChainDropdown.js b/src/components/header/auth/ChainDropdown.js new file mode 100644 index 000000000..1465f203c --- /dev/null +++ b/src/components/header/auth/ChainDropdown.js @@ -0,0 +1,33 @@ +import React from 'react'; +import supportedNetwork from './SupportedNetwork'; +import { CAvatar, CDropdown, CDropdownToggle, CDropdownMenu, CDropdownItem } from '@coreui/react'; + +const ChainDropdown = ({ chains, chain, switchNetwork, isLoading, pendingChainId }) => { + const findToken = (name) => { + return supportedNetwork.find((x) => x.name === name); + }; + + return ( + + + {findToken(chain.name) ? '' : 'Unsupported Network Choosen'} + + + + {chains.map((x) => ( + switchNetwork?.(x.id)} + > + + {x.name} + {isLoading && pendingChainId === x.id && ' (switching)'} + + ))} + + + ); +}; + +export default ChainDropdown; From 43649188276edb44543b035d4975533091dde28f Mon Sep 17 00:00:00 2001 From: Behnam Jaberi Date: Mon, 3 Jul 2023 17:58:17 +0330 Subject: [PATCH 05/11] Remove unused files --- .../header/auth/AuthHeaderDropDown.js | 83 ------------------- 1 file changed, 83 deletions(-) delete mode 100644 src/components/header/auth/AuthHeaderDropDown.js diff --git a/src/components/header/auth/AuthHeaderDropDown.js b/src/components/header/auth/AuthHeaderDropDown.js deleted file mode 100644 index c27e31fb1..000000000 --- a/src/components/header/auth/AuthHeaderDropDown.js +++ /dev/null @@ -1,83 +0,0 @@ -import React from "react"; -import { useWeb3Modal } from '@web3modal/react' -import { useNetwork, useSwitchNetwork, useAccount } from 'wagmi' - -import { - CAvatar, - CBadge, - CButton, - CDropdown, - CDropdownMenu, - CDropdownItem, - CDropdownToggle -} from '@coreui/react' -import ethIcon from '../../../assets/images/tokens/eth.png' -import arbitIcon from '../../../assets/images/tokens/arbitrum.svg' -import maticIcon from '../../../assets/images/tokens/polygon.svg' - - - -const ConnectWalletButton = () => { - const { chain } = useNetwork() - const { open } = useWeb3Modal() - const { chains, isLoading, pendingChainId, switchNetwork } = useSwitchNetwork() - const { address, status } = useAccount() - const supportedNetwork = [ - { - "name": "Ethereum", - "cover": ethIcon - }, - { - "name": "Arbitrum One", - "cover": arbitIcon - }, { - "name": "Polygon", - "cover": maticIcon - } - ] - - const findToken = (name) => { - return supportedNetwork.find(x => x.name === name) - } - - return ( - <> -
- open()} color="secondary" variant="outline" - className={address ? 'w-50 text-truncate h-75' : 'w-auto'}> - {address ? address : 'Connect Your Wallet'} - - {chain && - - - {findToken(chain.name) ? '' : 'Unsupported Network Choosen'} - - {findToken(chain.name) && - New alerts - } - - - {chains.map((x) => ( switchNetwork?.(x.id)} - > - - {x.name} - {isLoading && pendingChainId === x.id && ' (switching)'} - ) - )} - - } -
- - ) -}; - -export default ConnectWalletButton; \ No newline at end of file From b0e46b4b4b06f52ad176bb6f3b439a0723d739d9 Mon Sep 17 00:00:00 2001 From: Behnam Jaberi Date: Mon, 3 Jul 2023 17:59:22 +0330 Subject: [PATCH 06/11] Define connect wallet button and add to header --- src/components/AppHeader.js | 53 ++++--------- src/components/header/auth/index.js | 116 +++++++++++++++++++++++++++- 2 files changed, 131 insertions(+), 38 deletions(-) diff --git a/src/components/AppHeader.js b/src/components/AppHeader.js index 3d26dabb3..e0d226a67 100644 --- a/src/components/AppHeader.js +++ b/src/components/AppHeader.js @@ -1,6 +1,7 @@ -import React from 'react' -import { NavLink } from 'react-router-dom' -import { useSelector, useDispatch } from 'react-redux' +import React from 'react'; +import { NavLink } from 'react-router-dom'; +import { useSelector, useDispatch } from 'react-redux'; +import { setSidebarShow } from '../redux/actions'; import { CContainer, CHeader, @@ -10,41 +11,24 @@ import { CHeaderToggler, CNavLink, CNavItem, -} from '@coreui/react' -import CIcon from '@coreui/icons-react' -import { cilBell, cilEnvelopeOpen, cilList, cilMenu } from '@coreui/icons' +} from '@coreui/react'; +import CIcon from '@coreui/icons-react'; +import { cilBell, cilEnvelopeOpen, cilList, cilMenu } from '@coreui/icons'; -import { AppBreadcrumb } from './index' -import { AuthHeaderDropdown } from './header/auth/index' -import { logo } from 'src/assets/brand/logo' - -// Wagnumi Auth // -import { EthereumClient, w3mConnectors, w3mProvider } from '@web3modal/ethereum' -import { Web3Modal } from '@web3modal/react' -import { configureChains, createConfig, WagmiConfig } from 'wagmi' -import { arbitrum, mainnet, polygon } from 'wagmi/chains' - -const chains = [arbitrum, mainnet, polygon] -const projectId = 'YOUR_PROJECT_ID' - -const { publicClient } = configureChains(chains, [w3mProvider({ projectId })]) -const wagmiConfig = createConfig({ - autoConnect: true, - connectors: w3mConnectors({ projectId, version: 1, chains }), - publicClient -}) +import { AppBreadcrumb } from './index'; +import { logo } from 'src/assets/brand/logo'; +import WagmiAuth from './header/wagmi'; // Import the WagmiAuth component const AppHeader = () => { - const dispatch = useDispatch() - const ethereumClient = new EthereumClient(wagmiConfig, chains) - const sidebarShow = useSelector((state) => state.sidebarShow) + const dispatch = useDispatch(); + const sidebarShow = useSelector((state) => state.sidebarShow); return ( dispatch({ type: 'set', sidebarShow: !sidebarShow })} + onClick={() => dispatch(setSidebarShow(!sidebarShow))} > @@ -66,10 +50,7 @@ const AppHeader = () => { - - - - + {/* Render the WagmiAuth component */} @@ -94,7 +75,7 @@ const AppHeader = () => { - ) -} + ); +}; -export default AppHeader +export default AppHeader; diff --git a/src/components/header/auth/index.js b/src/components/header/auth/index.js index fc48eaf49..abeefb042 100644 --- a/src/components/header/auth/index.js +++ b/src/components/header/auth/index.js @@ -1,3 +1,115 @@ -import AuthHeaderDropdown from './AuthHeaderDropDown' +import React, { useState, useEffect } from 'react'; +import { useWeb3Modal } from '@web3modal/react'; +import { useNetwork, useSwitchNetwork, useAccount } from 'wagmi'; +import { useDispatch, useSelector } from 'react-redux'; +import { setToken } from '../../../redux/actions'; +import { useSignMessage } from 'wagmi'; +import ChainDropdown from './ChainDropdown'; +import WalletDropdown from './WalletDropdown'; +import supportedNetwork from './SupportedNetwork'; +import { getNonce, login } from '../../../services/apiServices'; +import { CButton } from '@coreui/react'; +import { ToastContainer, toast } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; -export { AuthHeaderDropdown } +const ConnectWalletButton = () => { + const [visible, setVisible] = useState(false); + const { chain } = useNetwork(); + const { open } = useWeb3Modal(); + const { chains, isLoading, pendingChainId, switchNetwork } = useSwitchNetwork(); + const { address, status } = useAccount(); + const { data, error, signMessage } = useSignMessage(); + const dispatch = useDispatch(); + const token = useSelector((state) => state.token); + + const findToken = (name) => { + return supportedNetwork.find((x) => x.name === name); + }; + + const handleDisconnect = () => { + setVisible(false); + dispatch(setToken('')); // Reset token in store + }; + + useEffect(() => { + if (!address) { + handleDisconnect(); + } + }, [address, handleDisconnect]); + + const signIn = async () => { + try { + const response = await getNonce(address); + if (response) { + try { + const message = response.message; + await signMessage({ message: message }); + if (!error && data !== undefined) { + getToken(data, address); + } + } catch (error) { + console.log('Error:', error); + toast.error('An error occurred. Please try again later.'); + } + } + } catch (error) { + console.log('Error:', error); + toast.error('An error occurred. Please try again later.'); + } + }; + + const getToken = async (signature, address) => { + try { + if (signature) { + const response = await login(address, signature); + if (response) { + setVisible(true); + dispatch(setToken(response.access_token)); + } else { + // Handle the error condition if needed + } + } + } catch (error) { + console.log('Error:', error); + } + }; + + return ( + <> + +
+ {!address && ( + open()} + color="primary" + className={address ? 'w-50 text-truncate h-75 rounded-pill' : 'w-auto rounded-pill'} + > + Connect + + )} + {address && ( + + )} + {chain && ( + + )} +
+ + ); +}; + +export default ConnectWalletButton; From 2b907e06e08157161c23a26aa101fdf62cf09148 Mon Sep 17 00:00:00 2001 From: Behnam Jaberi Date: Mon, 3 Jul 2023 17:59:58 +0330 Subject: [PATCH 07/11] Add services --- src/services/api.js | 52 +++++++++++++++++++++++++++++++++++++ src/services/apiServices.js | 24 +++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/services/api.js create mode 100644 src/services/apiServices.js diff --git a/src/services/api.js b/src/services/api.js new file mode 100644 index 000000000..9e8ba152a --- /dev/null +++ b/src/services/api.js @@ -0,0 +1,52 @@ +import axios from 'axios'; + +class ReactApiPlugin { + setAuthToken(token) { + axios.defaults.headers.common['Authorization'] = `Bearer ${token}`; + } + + clearAuthToken() { + delete axios.defaults.headers.common['Authorization']; + } + + async putData(url, data, config = {}) { + try { + const response = await axios.put(url, data, config); + return response.data; + } catch (error) { + if (error.response) { + throw new Error(error.response.data.message); + } else { + throw new Error('Network error'); + } + } + } + + async getData(url, config = {}) { + try { + const response = await axios.get(url, config); + return response.data; + } catch (error) { + if (error.response) { + throw new Error(error.response.data.message); + } else { + throw new Error('Network error'); + } + } + } + + async postData(url, data, config = {}) { + try { + const response = await axios.post(url, data, config); + return response.data; + } catch (error) { + if (error.response) { + throw new Error(error.response.data.message); + } else { + throw new Error('Network error'); + } + } + } +} + +export default new ReactApiPlugin(); \ No newline at end of file diff --git a/src/services/apiServices.js b/src/services/apiServices.js new file mode 100644 index 000000000..5777a078c --- /dev/null +++ b/src/services/apiServices.js @@ -0,0 +1,24 @@ +import apiPlugin from './api'; +const API_URL = "https://nestapi.treejer.com" + +export const getNonce = async (address) => { + try { + const response = await apiPlugin.getData(`${API_URL}/nonce/${address}`); + return response; + } catch (error) { + console.log('Error:', error); + throw error; + } +}; + +export const login = async (address, signature) => { + try { + const response = await apiPlugin.postData(`${API_URL}/login/${address}`, { + signature: signature, + }); + return response; + } catch (error) { + console.log('Error:', error); + throw error; + } +}; From f1b5286fdfd0ca4942003d32ffcc07b359c90de6 Mon Sep 17 00:00:00 2001 From: Behnam Jaberi Date: Mon, 3 Jul 2023 18:01:58 +0330 Subject: [PATCH 08/11] Define store and add to app and index js --- src/App.js | 27 ++++++++++++++++----------- src/index.js | 2 +- src/redux/actionTypes.js | 4 ++++ src/redux/actions.js | 22 ++++++++++++++++++++++ src/redux/reducer.js | 35 +++++++++++++++++++++++++++++++++++ src/redux/store.js | 8 ++++++++ src/store.js | 17 ----------------- 7 files changed, 86 insertions(+), 29 deletions(-) create mode 100644 src/redux/actionTypes.js create mode 100644 src/redux/actions.js create mode 100644 src/redux/reducer.js create mode 100644 src/redux/store.js delete mode 100644 src/store.js diff --git a/src/App.js b/src/App.js index 7c2488188..8fbf1e85a 100644 --- a/src/App.js +++ b/src/App.js @@ -1,6 +1,9 @@ import React, { Component, Suspense } from 'react' +import { Provider } from 'react-redux' import { HashRouter, Route, Routes } from 'react-router-dom' import './scss/style.scss' +import store from './redux/store' + const loading = (
@@ -20,17 +23,19 @@ const Page500 = React.lazy(() => import('./views/pages/page500/Page500')) class App extends Component { render() { return ( - - - - } /> - } /> - } /> - } /> - } /> - - - + + + + + } /> + } /> + } /> + } /> + } /> + + + + ) } } diff --git a/src/index.js b/src/index.js index d19a3bcd3..24e08e724 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,7 @@ import { createRoot } from 'react-dom/client' import App from './App' import reportWebVitals from './reportWebVitals' import { Provider } from 'react-redux' -import store from './store' +import store from './redux/store' createRoot(document.getElementById('root')).render( diff --git a/src/redux/actionTypes.js b/src/redux/actionTypes.js new file mode 100644 index 000000000..ba3b8573f --- /dev/null +++ b/src/redux/actionTypes.js @@ -0,0 +1,4 @@ +// actionTypes.js +export const SET_TOKEN = 'SET_TOKEN'; +export const SET_USER = 'SET_USER'; +export const SET_SIDEBAR_SHOW = 'SET_SIDEBAR_SHOW'; diff --git a/src/redux/actions.js b/src/redux/actions.js new file mode 100644 index 000000000..9c3758240 --- /dev/null +++ b/src/redux/actions.js @@ -0,0 +1,22 @@ +// actions.js +// Import action types +import { SET_TOKEN, SET_USER, SET_SIDEBAR_SHOW } from './actionTypes'; + + +// Action creators +export const setToken = (token) => ({ + type: SET_TOKEN, + payload: token +}); + +export const setUser = (user) => ({ + type: SET_USER, + payload: user +}); + +export const setSidebarShow = (show) => { + return { + type: SET_SIDEBAR_SHOW, + payload: show, + }; +}; \ No newline at end of file diff --git a/src/redux/reducer.js b/src/redux/reducer.js new file mode 100644 index 000000000..a33c65b30 --- /dev/null +++ b/src/redux/reducer.js @@ -0,0 +1,35 @@ +// reducer.js +// Import action types +import { SET_TOKEN, SET_USER, SET_SIDEBAR_SHOW } from './actionTypes'; + +// Initial state +const initialState = { + sidebarShow: true, + token: null, + user: null +}; + +// Reducer +const reducer = (state = initialState, action) => { + switch (action.type) { + case SET_TOKEN: + return { + ...state, + token: action.payload + }; + case SET_USER: + return { + ...state, + user: action.payload + }; + case SET_SIDEBAR_SHOW: + return { + ...state, + sidebarShow: action.payload + }; + default: + return state; + } +}; + +export default reducer; diff --git a/src/redux/store.js b/src/redux/store.js new file mode 100644 index 000000000..1ee3a019c --- /dev/null +++ b/src/redux/store.js @@ -0,0 +1,8 @@ +import { createStore, applyMiddleware } from 'redux'; +import thunk from 'redux-thunk'; +import reducer from './reducer'; + +// Create the store +const store = createStore(reducer, applyMiddleware(thunk)); + +export default store; diff --git a/src/store.js b/src/store.js deleted file mode 100644 index ab446364c..000000000 --- a/src/store.js +++ /dev/null @@ -1,17 +0,0 @@ -import { createStore } from 'redux' - -const initialState = { - sidebarShow: true, -} - -const changeState = (state = initialState, { type, ...rest }) => { - switch (type) { - case 'set': - return { ...state, ...rest } - default: - return state - } -} - -const store = createStore(changeState) -export default store From b35b341d1bb10f8ac5233f414b696dfe2785d2dd Mon Sep 17 00:00:00 2001 From: Behnam Jaberi Date: Mon, 3 Jul 2023 18:03:25 +0330 Subject: [PATCH 09/11] Update package json file --- package.json | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index da08efaab..32354716c 100644 --- a/package.json +++ b/package.json @@ -29,22 +29,39 @@ "@coreui/react": "^4.6.0", "@coreui/react-chartjs": "^2.1.2", "@coreui/utils": "^2.0.1", + "@web3-react/core": "^8.2.0", + "@web3-react/injected-connector": "^6.0.7", + "@web3-react/walletconnect": "^8.2.0", + "@web3modal/ethereum": "^2.4.5", + "@web3modal/react": "^2.4.5", + "@web3modal/sign-react": "^2.4.7", "chart.js": "^3.9.1", "classnames": "^2.3.2", "core-js": "^3.29.0", + "ethers": "^6.6.0", "prop-types": "^15.8.1", "react": "^18.2.0", "react-app-polyfill": "^3.0.0", "react-dom": "^18.2.0", - "react-redux": "^8.0.5", + "react-ranger": "^2.1.0", + "react-redux": "^8.1.1", "react-router-dom": "^6.8.2", - "redux": "4.2.1", - "simplebar-react": "^2.4.3" + "react-toastify": "^9.1.3", + "redux": "^4.2.1", + "redux-persist": "^6.0.0", + "redux-saga": "^1.2.3", + "redux-thunk": "^2.4.2", + "simplebar-react": "^2.4.3", + "wagmi": "^1.2.0", + "web3": "^4.0.2", + "web3-core": "^4.0.1", + "web3-errors": "^1.0.0" }, "devDependencies": { "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", + "dotenv": "^16.3.1", "eslint-config-prettier": "^8.7.0", "eslint-plugin-prettier": "^4.2.1", "prettier": "2.8.4", @@ -56,4 +73,4 @@ "node": ">=10", "npm": ">=6" } -} +} \ No newline at end of file From d6f3952a76982af055a2dbb687ee5b376f415b7d Mon Sep 17 00:00:00 2001 From: Behnam Jaberi Date: Mon, 3 Jul 2023 18:05:07 +0330 Subject: [PATCH 10/11] Update package json file --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 32354716c..c8a8078fe 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "redux-saga": "^1.2.3", "redux-thunk": "^2.4.2", "simplebar-react": "^2.4.3", + "viem": "^1.0.7", "wagmi": "^1.2.0", "web3": "^4.0.2", "web3-core": "^4.0.1", From bdfd03106a83673c066c0fcaee64c7771c4fbcb4 Mon Sep 17 00:00:00 2001 From: Behnam Jaberi Date: Mon, 3 Jul 2023 18:23:21 +0330 Subject: [PATCH 11/11] Update readme file --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 1185d8047..3dba05b94 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,18 @@ CoreUI is meant to be the UX game changer. Pure & transparent code is devoid of * [Support CoreUI Development](#support-coreui-development) * [Copyright and License](#copyright-and-license) +## Login and Connect Wallet + +If you want to add login and connect wallet functionality to your application, you can use the Wagmi library. Wagmi is a collection of React Hooks that makes it easy to work with Ethereum, including connecting wallets, displaying ENS and balance information, signing messages, interacting with contracts, and more. + +To get started with Wagmi, you can follow these steps: + +1. Install the Wagmi library and the necessary dependencies in your React project: + + ```bash + npm install wagmi viem + You can read more about that [here](https://wagmi.sh) + ## Versions * [CoreUI Free Bootstrap Admin Template](https://github.com/coreui/coreui-free-bootstrap-admin-template)