From 6bbac8a83f5a5095e7f6d66430c0acdf66b291ca Mon Sep 17 00:00:00 2001 From: shendel Date: Mon, 18 Sep 2023 14:27:07 +0300 Subject: [PATCH 1/5] admin panel - allow configure confirms count --- src/pages/Settings/Contracts.tsx | 20 +++++++++++++++++--- src/pages/Settings/FetchMainConfig.tsx | 6 +++++- src/state/application/actions.ts | 2 +- src/state/application/updater.ts | 7 ++++--- tsconfig.json | 2 +- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/pages/Settings/Contracts.tsx b/src/pages/Settings/Contracts.tsx index 4e75fd4f..6a72d7ac 100644 --- a/src/pages/Settings/Contracts.tsx +++ b/src/pages/Settings/Contracts.tsx @@ -1,3 +1,4 @@ +// @ts-nocheck import React, { useState, useEffect, useCallback, useRef } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' @@ -316,11 +317,15 @@ export default function Contracts() { const [routerChainId, setRouterChainId] = useState('') const [routerAddress, setRouterAddress] = useState('') + const [routerConfirmCount, setRouterConfirmCount] = useState(3) useEffect(() => { if (chainId !== undefined && stateRouterAddress[chainId]) { setRouterChainId(String(chainId)) setRouterAddress(stateRouterAddress[chainId]) + if (stateAppSettings?.routerConfigs[`${chainId}:${stateRouterAddress[chainId]}`]) { + setRouterConfirmCount(stateAppSettings.routerConfigs[`${chainId}:${stateRouterAddress[chainId]}`].confirmations) + } } else { setRouterChainId('') setRouterAddress('') @@ -354,14 +359,14 @@ export default function Contracts() { const tx = await routerConfigSigner.setChainConfig(routerChainId, { BlockChain: name, RouterContract: routerAddress, - Confirmations: 3, + Confirmations: routerConfirmCount, InitialHeight: 0 }) const receipt = await tx.wait() if (receipt.status) { - dispatch(updateRouterData({ chainId: Number(routerChainId), routerAddress: routerAddress })) + dispatch(updateRouterData({ chainId: Number(routerChainId), routerAddress: routerAddress, routerConfirmCount: routerConfirmCount })) addTransaction( { hash: receipt.transactionHash }, { @@ -476,13 +481,16 @@ export default function Contracts() { if (selectedContract !== `-`) { const { chainId, - address + address, + confirmations } = appSettings.routerConfigs[selectedContract] setRouterChainId(`${chainId}`) setRouterAddress(address) + setRouterConfirmCount(confirmations) } else { setRouterChainId(``) setRouterAddress(``) + setRouterConfirmCount(3) } } @@ -771,6 +779,12 @@ export default function Contracts() { value={routerAddress} onChange={event => setRouterAddress(event.target.value)} /> + {t('routerConfirmCount')} + setRouterConfirmCount(event.target.value)} + /> {onConfigNetwork ? ( diff --git a/src/pages/Settings/FetchMainConfig.tsx b/src/pages/Settings/FetchMainConfig.tsx index fe450c35..3359eefa 100644 --- a/src/pages/Settings/FetchMainConfig.tsx +++ b/src/pages/Settings/FetchMainConfig.tsx @@ -1,3 +1,4 @@ +// @ts-nocheck import React, { useState, useEffect, useRef } from 'react' import { useTranslation } from 'react-i18next' import { ERC20_ABI } from '../../constants/abis/erc20' @@ -105,6 +106,7 @@ export default function FetchMainConfig({ // @ts-ignore const crosschainTokens: any = {} const chainRouters: any = {} + const chainRoutersConfirmsCount: any = {} useMulticall(mainConfigChainId, multicallDataTokenConfigs) .then((contractTokenConfigs) => { @@ -117,6 +119,7 @@ export default function FetchMainConfig({ switch (method) { case `getChainConfig`: chainRouters[callData.tokenChainId] = aData.RouterContract + chainRoutersConfirmsCount[callData.tokenChainId] = aData.Confirmations.toNumber() break; case `getTokenConfig`: const { @@ -262,7 +265,8 @@ export default function FetchMainConfig({ const chainRouterAddress = chainRouters[chainId] updatedRouterConfigs[`${chainId}:${chainRouterAddress}`] = { address: chainRouterAddress, - chainId + chainId, + confirmations: chainRoutersConfirmsCount[chainId] } }) diff --git a/src/state/application/actions.ts b/src/state/application/actions.ts index 97963436..b424e2bd 100644 --- a/src/state/application/actions.ts +++ b/src/state/application/actions.ts @@ -101,7 +101,7 @@ export type AppData = { export type AppDataKeys = keyof AppData -export const updateRouterData = createAction<{ chainId: number; routerAddress: string }>('application/updateRouterData') +export const updateRouterData = createAction<{ chainId: number; routerAddress: string, routerConfirmCount: number }>('application/updateRouterData') export const setAppManagement = createAction<{ status: boolean }>('application/setAppManagement') export const retrieveAppData = createAction('application/retrieveAppData') export const updateAppOptions = createAction<{ key: AppDataKeys; value: AppData[AppDataKeys] }[]>( diff --git a/src/state/application/updater.ts b/src/state/application/updater.ts index 3b7351fa..890a26a1 100644 --- a/src/state/application/updater.ts +++ b/src/state/application/updater.ts @@ -43,15 +43,16 @@ export default function Updater(): null { const fetch = async () => { if (!routerConfig || !chainId) return - const { RouterContract } = await routerConfig.methods.getChainConfig(chainId).call() + const routerData = await routerConfig.methods.getChainConfig(chainId).call() + const { RouterContract } = routerData - dispatch(updateRouterData({ chainId, routerAddress: RouterContract === ZERO_ADDRESS ? '' : RouterContract })) + dispatch(updateRouterData({ chainId, routerAddress: RouterContract === ZERO_ADDRESS ? '' : RouterContract, routerConfirmCount: 3 })) } if (routerConfig && chainId) { fetch() } else { - dispatch(updateRouterData({ chainId: chainId || 0, routerAddress: '' })) + dispatch(updateRouterData({ chainId: chainId || 0, routerAddress: '', routerConfirmCount: 3 })) } }, [chainId, mainConfigAddress, mainConfigChainId, routerConfig]) diff --git a/tsconfig.json b/tsconfig.json index bd37dd90..21b779c5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,7 @@ "strict": false, "alwaysStrict": false, "strictNullChecks": true, - "noUnusedLocals": true, + "noUnusedLocals": false, "noFallthroughCasesInSwitch": true, "noImplicitAny": true, "noImplicitThis": true, From 46db3ae22b1ad04fe08150957d9d2801d51e3332 Mon Sep 17 00:00:00 2001 From: shendel Date: Tue, 19 Sep 2023 14:16:59 +0300 Subject: [PATCH 2/5] show pools info --- src/state/pools/updater.ts | 218 ++++++++++--------------------- src/utils/bridge/getBalanceV2.ts | 5 +- 2 files changed, 72 insertions(+), 151 deletions(-) diff --git a/src/state/pools/updater.ts b/src/state/pools/updater.ts index 7a3f1d1c..8dbcabd6 100644 --- a/src/state/pools/updater.ts +++ b/src/state/pools/updater.ts @@ -1,163 +1,85 @@ +// @ts-nocheck import { useCallback } from 'react' import useInterval from '../../hooks/useInterval' // import { useDispatch } from 'react-redux' import { useDispatch } from 'react-redux' // import axios from 'axios' // import config from '../../config' -// import { useAppState } from '../../state/application/hooks' -import {poolLiquidity} from './actions' +import { useAppState } from '../../state/application/hooks' +import { poolLiquidity } from './actions' +import { getUrlData } from '../../utils/tools/axios' +import { getNodeTotalsupply, getBlandTs } from '../../utils/bridge/getBalanceV2' +import { useActiveWeb3React } from '../../hooks' export default function Updater(): null { const dispatch = useDispatch() - console.log('>>> call state/pools/update') - // const { apiAddress } = useAppState() + + const { apiAddress } = useAppState() const getPools = useCallback(() => { - /* - axios.get(`${apiAddress}/data/router/pools`).then(res => { - const {status, data } = res - if (status === 200) { - const testData = { - "1": { - "0xdac17f958d2ee523a2206206994597c13d831ec7": { - "logoUrl": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png", - "name": "TetherUSD", - "symbol": "USDT", - "decimals": 6, - "anyToken": "0x22648c12acd87912ea1710357b1302c6a4154ebc", - "liquidity": "9009221334195" - } - }, - "56": { - "0x55d398326f99059ff775485246999027b3197955": { - "logoUrl": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png", - "name": "TetherUSD", - "symbol": "USDT", - "decimals": 18, - "anyToken": "0xedf0c420bc3b92b961c6ec411cc810ca81f5f21a", - "liquidity": "5756135762036213167560" - } - }, - "66": { - "0x382bb369d343125bfb2117af9c149795c6c65c50": { - "logoUrl": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png", - "name": "USDT", - "symbol": "USDT", - "decimals": 18, - "anyToken": "0x0dcb0cb0120d355cde1ce56040be57add0185baa", - "liquidity": "8358674931031277832025" - } - }, - "128": { - "0xa71edc38d189767582c38a3145b5873052c3e47a": { - "logoUrl": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png", - "name": "Heco-Peg USDT Token", - "symbol": "USDT", - "decimals": 18, - "anyToken": "0xfea7a6a0b346362bf88a9e4a88416b77a57d6c2a", - "liquidity": "2210305595209176178171" - } - }, - "137": { - "0xc2132d05d31c914a87c6611c10748aeb04b58e8f": { - "logoUrl": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png", - "name": "(PoS)TetherUSD", - "symbol": "USDT", - "decimals": 6, - "anyToken": "0xe3eeda11f06a656fcaee19de663e84c7e61d3cac", - "liquidity": "24406406214" - } - }, - "250": { - "0x049d68029688eabf473097a2fc38ef61633a3c7a": { - "logoUrl": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png", - "name": "FrappedUSDT", - "symbol": "fUSDT", - "decimals": 6, - "anyToken": "0x2823d10da533d9ee873fed7b16f4a962b2b7f181", - "liquidity": "28719720236637" - } - } - } - dispatch(poolLiquidity({poolLiquidity: testData})) - } - }) - */ - /* - const testData = { - "1": { - "0xdac17f958d2ee523a2206206994597c13d831ec7": { - "logoUrl": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png", - "name": "TetherUSD", - "symbol": "USDT", - "decimals": 6, - "anyToken": "0x22648c12acd87912ea1710357b1302c6a4154ebc", - "liquidity": "9009221334195" - } - }, - "56": { - "0x55d398326f99059ff775485246999027b3197955": { - "logoUrl": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png", - "name": "TetherUSD", - "symbol": "USDT", - "decimals": 18, - "anyToken": "0xedf0c420bc3b92b961c6ec411cc810ca81f5f21a", - "liquidity": "5756135762036213167560" - } - }, - "97": { - "0x6e9c98a8a481BF038Ba7e1d669a0086547dd144E": { - "logoUrl": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png", - "name": "TetherUSD", - "symbol": "USDT", - "decimals": 8, - "anyToken": "0xc0c3394781c23faa538a506b3c96fb59c050bed8", - "liquidity": "5756135762036213167560" - } - }, - "66": { - "0x382bb369d343125bfb2117af9c149795c6c65c50": { - "logoUrl": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png", - "name": "USDT", - "symbol": "USDT", - "decimals": 18, - "anyToken": "0x0dcb0cb0120d355cde1ce56040be57add0185baa", - "liquidity": "8358674931031277832025" - } - }, - "128": { - "0xa71edc38d189767582c38a3145b5873052c3e47a": { - "logoUrl": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png", - "name": "Heco-Peg USDT Token", - "symbol": "USDT", - "decimals": 18, - "anyToken": "0xfea7a6a0b346362bf88a9e4a88416b77a57d6c2a", - "liquidity": "2210305595209176178171" - } - }, - "137": { - "0xc2132d05d31c914a87c6611c10748aeb04b58e8f": { - "logoUrl": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png", - "name": "(PoS)TetherUSD", - "symbol": "USDT", - "decimals": 6, - "anyToken": "0xe3eeda11f06a656fcaee19de663e84c7e61d3cac", - "liquidity": "24406406214" - } - }, - "250": { - "0x049d68029688eabf473097a2fc38ef61633a3c7a": { - "logoUrl": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png", - "name": "FrappedUSDT", - "symbol": "fUSDT", - "decimals": 6, - "anyToken": "0x2823d10da533d9ee873fed7b16f4a962b2b7f181", - "liquidity": "28719720236637" + const url = `${apiAddress}/config` + + getUrlData(url) + .then(async (tokenList: any) => { + if (tokenList.msg && tokenList.msg == 'Success' && tokenList.data && tokenList.data.length > 0) { + const callsByChainId = {} + const tokensByChainsMap = {} + + tokenList.data.forEach((tokenGroup) => { + tokenGroup.multichainTokens.forEach((mcToken) => { + //if (mcToken.chainId != 1229) { /* Dont fork for me without VPN - for dev skip it chain */ + callsByChainId[mcToken.chainId] = callsByChainId[mcToken.chainId] || [] + callsByChainId[mcToken.chainId].push({ + token: mcToken.anyswapToken.ContractAddress, + underlying: mcToken.anyswapToken.Underlying, + dec: mcToken.anyswapToken.Decimals + }) + + tokensByChainsMap[`${mcToken.chainId}:${mcToken.anyswapToken.ContractAddress}`] = { + name: mcToken.anyswapToken.TokenID, + symbol: mcToken.anyswapToken.TokenID, + decimals: mcToken.anyswapToken.Decimals, + anyToken: mcToken.anyswapToken.ContractAddress, + underlying: mcToken.anyswapToken.Underlying + } + //} + }) + }) + + const promiseList = Object.keys(callsByChainId).map((chainId) => { + return new Promise((resolve) => { + try { + getBlandTs(callsByChainId[chainId], chainId).then((res: any) => { + resolve({ + chainId, + data: res + }) + }) + } catch (err) { + console.log('>>> POOL ERROR', err) + } + }) + }) + Promise.all(promiseList).then((res) => { + const retData = {} + res.forEach(({ chainId, data }) => { + retData[chainId] = {} + Object.keys(data).forEach((anyAddress) => { + retData[chainId][tokensByChainsMap[`${chainId}:${anyAddress}`].underlying] = { + ...tokensByChainsMap[`${chainId}:${anyAddress}`], + liquidity: data[anyAddress].wei_ts + } + }) + }) + dispatch(poolLiquidity({poolLiquidity: retData})) + }) } - } - } -*/ - dispatch(poolLiquidity({poolLiquidity: {}/*testData*/})) + }) + .catch(error => { + console.log('Pool error', error) + }) + + dispatch(poolLiquidity({poolLiquidity: {} })) }, [dispatch]) useInterval(getPools, 1000 * 30) diff --git a/src/utils/bridge/getBalanceV2.ts b/src/utils/bridge/getBalanceV2.ts index 729ff703..591e1944 100644 --- a/src/utils/bridge/getBalanceV2.ts +++ b/src/utils/bridge/getBalanceV2.ts @@ -61,7 +61,7 @@ export function getNodeBalance(account?:any, token?:string, chainID?:any, dec?:a const SRCTOTALSUPPLY = 'SRCTOTALSUPPLY' -function getBlandTs(tokenList:any, chainId?:any, account?:string | null | undefined) { +export function getBlandTs(tokenList:any, chainId?:any, account?:string | null | undefined) { return new Promise(async(resolve) => { const len = tokenList.length const list:any = {} @@ -131,6 +131,7 @@ function getBlandTs(tokenList:any, chainId?:any, account?:string | null | undefi if (!list[arr[i].token]) list[arr[i].token] = {} list[arr[i].token][arr[i].key] = fromWei(balance, arr[i].dec) + list[arr[i].token][`wei_${arr[i].key}`] = balance.toString() } } } catch (error) { @@ -164,8 +165,6 @@ export function getNodeTotalsupply( } ] getBlandTs(tokenList, chainId, account).then((res: any) => { - // console.log(token) - // console.log(res) resolve(res) }) } From d1bf05cbb38a56296144d4d20ec16dad54474ed4 Mon Sep 17 00:00:00 2001 From: shendel Date: Wed, 20 Sep 2023 12:44:03 +0300 Subject: [PATCH 3/5] @typescript-eslint/no-unused-vars --- .eslintrc.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index 75d6a142..22a75d05 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -27,6 +27,7 @@ "prettier/prettier": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-var-requires": 0, - "@typescript-eslint/ban-ts-ignore": "off" + "@typescript-eslint/ban-ts-ignore": "off", + "@typescript-eslint/no-unused-vars": "off" } } \ No newline at end of file From 0bb9ef89c59165f4d4b32b24e928c48059328056 Mon Sep 17 00:00:00 2001 From: shendel Date: Wed, 20 Sep 2023 13:20:19 +0300 Subject: [PATCH 4/5] admin - menu links --- src/components/MenuListFactory/index.tsx | 105 +++++++++++++++++++++++ src/hooks/useAppData.ts | 3 + src/pages/Settings/Interface.tsx | 15 ++++ src/state/application/actions.ts | 1 + src/state/application/reducer.ts | 3 + 5 files changed, 127 insertions(+) create mode 100644 src/components/MenuListFactory/index.tsx diff --git a/src/components/MenuListFactory/index.tsx b/src/components/MenuListFactory/index.tsx new file mode 100644 index 00000000..f17b8f70 --- /dev/null +++ b/src/components/MenuListFactory/index.tsx @@ -0,0 +1,105 @@ +import React, { useState } from 'react' +import styled from 'styled-components' +import { Box } from 'rebass' +import { CleanButton, ButtonAdd } from '../Button' +import { RiCloseFill } from 'react-icons/ri' +import Accordion from '../Accordion' + +const List = styled.ul` + margin: 0; + padding: 0.4rem; + list-style: none; +` + +const Item = styled.li` + padding: 0.2rem 0; + display: flex; + align-items: center; + justify-content: space-between; +` + +const Overflow = styled.span` + overflow-x: auto; +` + +const RemoveButton = styled(CleanButton)` + width: auto; + padding: 0.3rem; +` + +const NewItemWrapper = styled(Box)` + display: flex; + align-items: center; +` + +const NewItemInput = styled.input<{ error: boolean }>` + border-radius: 0.5rem; + margin-right: 0.4rem !important; + ${({ error, theme }) => (error ? `border: 2px solid ${theme.red2} !important;` : '')} +` + +export default function MenuListFactory({ + title, + placeholder, + isValidItem, + items, + setItems +}: { + title: string + setItems: (callback: any) => void + isValidItem: (item: { title: string, address: string } ) => boolean + items: any[] + placeholder?: string +}) { + const [newItemTitle, setNewItemTitle] = useState('') + const [newItemAddress, setNewItemAddress] = useState('') + + const [itemError, setItemError] = useState(false) + + const onRemove = (targetIndex: number) => { + setItems((prevItems: any[]) => prevItems.filter((_, index) => index !== targetIndex)) + } + + const onNewItemTitleChange = (event: any) => { + setItemError(false) + setNewItemTitle(event.target.value) + } + const onNewItemAddressChange = (event: any) => { + setItemError(false) + setNewItemAddress(event.target.value) + } + + const onAdd = () => { + if (isValidItem({title: newItemTitle, address: newItemAddress})) { + setItems((prevItems: any[]) => [...prevItems, { title: newItemTitle, address: newItemAddress }]) + setNewItemTitle('') + setNewItemAddress('') + } else { + setItemError(true) + } + } + + return ( + + + {items.map((item, index) => ( + + {item.title} + ({item.address}) + onRemove(index)} title="Remove item"> + + + + ))} + + + +
Title:
+ +
Address:
+ + +
+
+ ) +} diff --git a/src/hooks/useAppData.ts b/src/hooks/useAppData.ts index f06174ef..cec204cb 100644 --- a/src/hooks/useAppData.ts +++ b/src/hooks/useAppData.ts @@ -21,6 +21,7 @@ const parseInfo = (info: string) => { elementsColorLight: '', elementsColorDark: '', socialLinks: [], + menuLinks: [], disableSourceCopyright: false, tokenIcons: {}, appSettings: { @@ -53,6 +54,7 @@ const parseInfo = (info: string) => { elementsColorDark, tokenIcons, socialLinks, + menuLinks, disableSourceCopyright, appSettings, } = crossChainSettings @@ -72,6 +74,7 @@ const parseInfo = (info: string) => { if (elementsColorLight) parsed.elementsColorLight = elementsColorLight if (elementsColorDark) parsed.elementsColorDark = elementsColorDark if (Array.isArray(socialLinks) && socialLinks.length) parsed.socialLinks = socialLinks + if (Array.isArray(menuLinks) && menuLinks.length) parsed.menuLinks = menuLinks if (disableSourceCopyright) parsed.disableSourceCopyright = disableSourceCopyright parsed.tokenIcons = (tokenIcons && Object.keys(tokenIcons).length) ? tokenIcons : {} } diff --git a/src/pages/Settings/Interface.tsx b/src/pages/Settings/Interface.tsx index f95627f9..97c6565d 100644 --- a/src/pages/Settings/Interface.tsx +++ b/src/pages/Settings/Interface.tsx @@ -13,6 +13,7 @@ import ColorSelector from '../../components/ColorSelector' import InputPanel from '../../components/InputPanel' import Toggle from '../../components/Toggle' import ListFactory from '../../components/ListFactory' +import MenuListFactory from '../../components/MenuListFactory' import { OptionWrapper } from './index' import { updateStorageData } from '../../utils/storage' @@ -71,6 +72,7 @@ export default function Interface() { elementsColorLight: stateElementsColorLight, elementsColorDark: stateElementsColorDark, socialLinks: stateSocialLinks, + menuLinks: stateMenuLinks, disableSourceCopyright: stateDisableSourceCopyright, tokenIcons: stateTokenIcons } = useAppState() @@ -120,6 +122,8 @@ export default function Interface() { } } + const [menuLinks, setMenuLinks] = useState(stateMenuLinks || []) + const [socialLinks, setSocialLinks] = useState(stateSocialLinks) const [disableSourceCopyright, setDisableSourceCopyright] = useState(stateDisableSourceCopyright) @@ -183,6 +187,7 @@ export default function Interface() { elementsColorLight, elementsColorDark, socialLinks, + menuLinks, tokenIcons: tokenIconsList, disableSourceCopyright }, @@ -321,6 +326,16 @@ export default function Interface() { /> + + { + return Boolean(validUrl.isUri(address)) && title != `` + }} + /> + elementsColorLight, elementsColorDark, socialLinks, + menuLinks, tokenIcons, disableSourceCopyright, appSettings @@ -94,6 +96,7 @@ export default createReducer(initialState, builder => if (elementsColorLight) state.elementsColorLight = elementsColorLight if (elementsColorDark) state.elementsColorDark = elementsColorDark if (Array.isArray(socialLinks) && socialLinks.length) state.socialLinks = socialLinks + if (Array.isArray(menuLinks) && menuLinks.length) state.menuLinks = menuLinks if (disableSourceCopyright) state.disableSourceCopyright = disableSourceCopyright state.tokenIcons = (tokenIcons && Object.keys(tokenIcons).length) ? tokenIcons : {} } From 336b41e6dc488c1fa6b7da7b041a282a1edb9d47 Mon Sep 17 00:00:00 2001 From: shendel Date: Wed, 20 Sep 2023 13:57:46 +0300 Subject: [PATCH 5/5] header menu items --- src/components/Header/NavList.tsx | 52 +++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/components/Header/NavList.tsx b/src/components/Header/NavList.tsx index 209c1849..8195a8fa 100644 --- a/src/components/Header/NavList.tsx +++ b/src/components/Header/NavList.tsx @@ -225,7 +225,7 @@ const StyledNavLink = styled(NavLink).attrs({ export default function NavList() { const { t } = useTranslation() const { account, active } = useActiveWeb3React() - const { owner, appManagement } = useAppState() + const { owner, appManagement, menuLinks } = useAppState() const dispatch = useDispatch() const [isOwner, setIsOwner] = useState(!owner || account?.toLowerCase() === owner?.toLowerCase()) @@ -241,6 +241,46 @@ export default function NavList() { return ( <> + {/* @@ -332,7 +372,15 @@ export default function NavList() { {t('pool')} - + {Array.isArray(menuLinks) && menuLinks.length && ( + <> + {menuLinks.map((item, key) => { + return ( + {item.title} + ) + })} + + )} {active && isOwner && ( {t('adminPanel')}