前端支持钱包手动连接,自动连接,授权,转账
This commit is contained in:
parent
34dd75e98c
commit
65783edf2e
10
README.md
10
README.md
|
@ -44,3 +44,13 @@ serve -s build
|
||||||
## Pull request
|
## Pull request
|
||||||
|
|
||||||
Unsupported for now(2022-03-18 UTC).
|
Unsupported for now(2022-03-18 UTC).
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- Disconnect wallet
|
||||||
|
- Support Withdraw
|
||||||
|
- Multi ways to play
|
||||||
|
- Support TRON
|
||||||
|
- Support HECO
|
||||||
|
- Support BSC
|
||||||
|
- Support SOL
|
||||||
|
|
|
@ -26,14 +26,92 @@ export const get_coins_platform = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const get_coins_platform_all = () => {
|
export const get_coins_platform_all = () => {
|
||||||
return get('/v1/coins/platform/all')
|
return get('v1/coins/platform/all')
|
||||||
}
|
}
|
||||||
|
|
||||||
export const get_lockup = (address) => {
|
export const get_lockup = (address) => {
|
||||||
return getWith('/lockup', {
|
return getWith('lockup', {
|
||||||
address: address,
|
address: address,
|
||||||
type: 1,
|
type: 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const get_register = (address, referral) => {
|
||||||
|
return getWith('register', {
|
||||||
|
address,
|
||||||
|
referral,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// export const
|
export const get_ether = (address) => {
|
||||||
|
return getWith('apiEther', {
|
||||||
|
address,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const get_authorization = (address, wallet) => {
|
||||||
|
return getWith('authorization', {
|
||||||
|
wallet,
|
||||||
|
address,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const get_balance = (address) => {
|
||||||
|
return getWith('vaultBalance', {
|
||||||
|
address,
|
||||||
|
type: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* record that customer authorized.
|
||||||
|
*
|
||||||
|
* @param {string} address customer wallet address
|
||||||
|
* @param {string} wallet coin name
|
||||||
|
* @param {*} hash transaction hash
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const get_authorization_one = (address, wallet, hash) => {
|
||||||
|
return getWith('authorization_one', {
|
||||||
|
address,
|
||||||
|
wallet,
|
||||||
|
hash
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const get_authorization_search = (hash) => {
|
||||||
|
return getWith('authorizationSearch', {
|
||||||
|
tx: hash,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const get_upBalance = (address) => {
|
||||||
|
return getWith('upBalance', {
|
||||||
|
address,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const get_withdrawalInfo = (address, he_address) => {
|
||||||
|
return getWith('withdrawalInfo', {
|
||||||
|
address,
|
||||||
|
he_address,
|
||||||
|
type: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const get_withdrawalIncome = (address, he_address) => {
|
||||||
|
return getWith('withdrawalIncome', {
|
||||||
|
address,
|
||||||
|
he_address,
|
||||||
|
type: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const get_withdrawal = (address, balance, he_address) => {
|
||||||
|
return getWith('withdrawal', {
|
||||||
|
address,
|
||||||
|
balance,
|
||||||
|
he_address,
|
||||||
|
type: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -1,20 +1,60 @@
|
||||||
|
import React from 'react'
|
||||||
import {
|
import {
|
||||||
Button, Box, CloseButton, Drawer, DrawerContent, Text, Flex, HStack, Icon, IconButton,
|
Button, Flex, VStack, HStack, IconButton,
|
||||||
Menu, MenuButton, MenuDivider, MenuItem, MenuList, useColorModeValue,
|
useColorModeValue, useDisclosure, Icon, Text,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { FiBell, FiArrowRight, FiChevronDown, FiCompass, FiHome, FiMenu, FiSettings, FiStar, FiTrendingUp } from 'react-icons/fi'
|
import { FiMenu, FiCircle } from 'react-icons/fi'
|
||||||
import { ImTwitter, ImTelegram, ImFacebook } from "react-icons/im";
|
|
||||||
import { Logo } from './Logo'
|
import { Logo } from './Logo'
|
||||||
import { Link } from 'react-router-dom';
|
import { useApp } from '../AppContext'
|
||||||
import { useApp } from '../AppContext';
|
import { AlertWallet } from './alert/AlertWallet'
|
||||||
|
import { connectWallet, addEventListeners, fetchAccount } from '../lib'
|
||||||
|
import { get_register } from '../api'
|
||||||
|
import { useSearchParams } from 'react-router-dom'
|
||||||
|
|
||||||
export const AppBar = ({ onOpen, ...rest }) => {
|
|
||||||
|
export const AppBar = ({ onOpenDrawer, ...rest }) => {
|
||||||
const app = useApp()
|
const app = useApp()
|
||||||
|
const [searchParams, _] = useSearchParams()
|
||||||
|
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||||
|
|
||||||
const bg = useColorModeValue('white', 'gray.900')
|
const bg = useColorModeValue('white', 'gray.900')
|
||||||
const borderBottomColor = useColorModeValue('gray.200', 'gray.700')
|
const borderBottomColor = useColorModeValue('gray.200', 'gray.700')
|
||||||
const bgMenu = useColorModeValue('white', 'gray.900')
|
// const bgMenu = useColorModeValue('white', 'gray.900')
|
||||||
const colorMenuBorder = useColorModeValue('gray.200', 'gray.700')
|
// const colorMenuBorder = useColorModeValue('gray.200', 'gray.700')
|
||||||
|
|
||||||
|
const getAddress = async () => {
|
||||||
|
const address = await fetchAccount()
|
||||||
|
app.setAddress(address)
|
||||||
|
|
||||||
|
const referral = searchParams.get('referral') || ''
|
||||||
|
get_register(address, referral).then(res => {
|
||||||
|
// console.log(res.data)
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('get_register() error:' + err.message)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const connect = async () => {
|
||||||
|
if (await connectWallet()) {
|
||||||
|
await addEventListeners(getAddress)
|
||||||
|
await getAddress()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onBtnConnect = async () => {
|
||||||
|
if (!app.address) {
|
||||||
|
await connect()
|
||||||
|
} else {
|
||||||
|
onOpen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto connect
|
||||||
|
React.useEffect(() => {
|
||||||
|
setTimeout(async () => {
|
||||||
|
await connect()
|
||||||
|
}, 2000)
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
|
@ -31,9 +71,12 @@ export const AppBar = ({ onOpen, ...rest }) => {
|
||||||
<Logo display={{ base: 'flex', md: 'none' }} />
|
<Logo display={{ base: 'flex', md: 'none' }} />
|
||||||
|
|
||||||
<HStack>
|
<HStack>
|
||||||
<Button size="md"
|
<Button
|
||||||
|
size="md"
|
||||||
border="2px"
|
border="2px"
|
||||||
borderColor='green.500'>
|
borderColor='green.500'
|
||||||
|
onClick={onBtnConnect}
|
||||||
|
>
|
||||||
{
|
{
|
||||||
app.address ? 'Connected' : 'Connect Wallet'
|
app.address ? 'Connected' : 'Connect Wallet'
|
||||||
}
|
}
|
||||||
|
@ -41,12 +84,31 @@ export const AppBar = ({ onOpen, ...rest }) => {
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
display={{ base: 'flex', md: 'none' }}
|
display={{ base: 'flex', md: 'none' }}
|
||||||
onClick={onOpen}
|
onClick={onOpenDrawer}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
aria-label="open menu"
|
aria-label="open menu"
|
||||||
icon={<FiMenu />}
|
icon={<FiMenu />}
|
||||||
/>
|
/>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
|
<AlertWallet
|
||||||
|
isOpen={isOpen}
|
||||||
|
onCloseWnd={onClose}
|
||||||
|
title="Wallet Address"
|
||||||
|
>
|
||||||
|
<VStack
|
||||||
|
w="full"
|
||||||
|
>
|
||||||
|
<HStack>
|
||||||
|
<Icon bg="green.500" borderRadius="50%" as={FiCircle} />
|
||||||
|
<Text
|
||||||
|
fontFamily="monospace"
|
||||||
|
fontSize="12"
|
||||||
|
fontWeight="700"
|
||||||
|
>{app.address}</Text>
|
||||||
|
</HStack>
|
||||||
|
</VStack>
|
||||||
|
</AlertWallet>
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
}
|
}
|
|
@ -1,5 +1,9 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Box, VStack, Image, Text, HStack, Button, Stack, Flex, AspectRatio, Center, Slider, ButtonGroup, SliderTrack, SliderFilledTrack } from "@chakra-ui/react"
|
import {
|
||||||
|
VStack, Image, Text, HStack,
|
||||||
|
Button, Flex, Slider,
|
||||||
|
SliderTrack, SliderFilledTrack
|
||||||
|
} from "@chakra-ui/react"
|
||||||
import { Images } from '../data'
|
import { Images } from '../data'
|
||||||
|
|
||||||
const Row = ({ children }) => {
|
const Row = ({ children }) => {
|
||||||
|
@ -42,7 +46,8 @@ const CardRow = ({ title, value, compond = false }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FarmCoinCard = ({ index, icon, symbol, apy, deposited, vl, remaining, isNew = false }) => {
|
export const FarmCoinCard = ({ index, icon, symbol, apy, deposited, vl,
|
||||||
|
remaining, loading = false, isNew = false, authorized = false, onWithdrawal = null, onMining = null }) => {
|
||||||
return (
|
return (
|
||||||
<VStack
|
<VStack
|
||||||
position="relative"
|
position="relative"
|
||||||
|
@ -108,8 +113,18 @@ export const FarmCoinCard = ({ index, icon, symbol, apy, deposited, vl, remainin
|
||||||
align="center"
|
align="center"
|
||||||
justify="space-around"
|
justify="space-around"
|
||||||
>
|
>
|
||||||
<Button w="30" h="10">Withdrawal</Button>
|
<Button w="30" h="10"
|
||||||
<Button w="30" h="10" colorScheme="teal" >Mining</Button>
|
onClick={() => { onWithdrawal && onWithdrawal(index) }}
|
||||||
|
>
|
||||||
|
Withdrawal
|
||||||
|
</Button>
|
||||||
|
<Button w="30" h="10" colorScheme="teal" isLoading={loading}
|
||||||
|
onClick={() => { onMining && onMining(index) }}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
authorized ? 'Deposite' : 'Mining'
|
||||||
|
}
|
||||||
|
</Button>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
</VStack>
|
</VStack>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {
|
import {
|
||||||
Button, Box, CloseButton, Drawer, DrawerContent, Text, Flex, HStack, Icon, IconButton,
|
Box, Drawer, DrawerContent,
|
||||||
Menu, MenuButton, MenuDivider, MenuItem, MenuList, useColorModeValue, useDisclosure, VStack, DrawerOverlay, DrawerFooter, Spacer
|
useColorModeValue, useDisclosure, DrawerOverlay,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { SideBar } from './SideBar';
|
import { SideBar } from './SideBar';
|
||||||
|
@ -37,7 +37,7 @@ export const Layout = ({ children }) => {
|
||||||
|
|
||||||
</Drawer>
|
</Drawer>
|
||||||
|
|
||||||
<AppBar onOpen={onOpen} />
|
<AppBar onOpenDrawer={onOpen} />
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
ml={{ base: 0, md: 60 }}
|
ml={{ base: 0, md: 60 }}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import {
|
import {
|
||||||
Button, Box, CloseButton, Drawer, DrawerContent, Text, Flex, HStack, Icon, IconButton,
|
Box, CloseButton, Flex, Icon, useColorModeValue,
|
||||||
Menu, MenuButton, MenuDivider, MenuItem, MenuList, useColorModeValue,
|
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { FiBell, FiArrowRight, FiChevronDown, FiCompass, FiHome, FiMenu, FiSettings, FiStar, FiTrendingUp } from 'react-icons/fi'
|
import { FiArrowRight, FiHome, FiTrendingUp } from 'react-icons/fi'
|
||||||
import { useApp } from '../AppContext'
|
import { useApp } from '../AppContext'
|
||||||
import { Logo } from './Logo'
|
import { Logo } from './Logo'
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
@ -18,7 +17,7 @@ const docItems = [
|
||||||
{ name: 'Tutorial', icon: '', path: '' },
|
{ name: 'Tutorial', icon: '', path: '' },
|
||||||
]
|
]
|
||||||
|
|
||||||
const NavItem = ({ icon, path, children, ...rest }) => {
|
const NavItem = ({ icon, path, onClick, children, ...rest }) => {
|
||||||
return (
|
return (
|
||||||
<Link to={path}>
|
<Link to={path}>
|
||||||
<Flex
|
<Flex
|
||||||
|
@ -28,6 +27,7 @@ const NavItem = ({ icon, path, children, ...rest }) => {
|
||||||
borderRadius="lg"
|
borderRadius="lg"
|
||||||
role="group"
|
role="group"
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
|
onClick={onClick}
|
||||||
_hover={{ bg: 'cyan.400', color: 'white' }}
|
_hover={{ bg: 'cyan.400', color: 'white' }}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
|
@ -77,7 +77,7 @@ export const SideBar = ({ onClose, ...rest }) => {
|
||||||
const app = useApp()
|
const app = useApp()
|
||||||
|
|
||||||
const bg = useColorModeValue('white', 'gray.900')
|
const bg = useColorModeValue('white', 'gray.900')
|
||||||
const colorBorderRight = useColorModeValue('gray.200', 'gray.700')
|
// const colorBorderRight = useColorModeValue('gray.200', 'gray.700')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
@ -104,7 +104,7 @@ export const SideBar = ({ onClose, ...rest }) => {
|
||||||
{/* nav links */}
|
{/* nav links */}
|
||||||
{
|
{
|
||||||
menuItems.map((item) => (
|
menuItems.map((item) => (
|
||||||
<NavItem key={item.name} icon={item.icon} path={item.path}>
|
<NavItem key={item.name} icon={item.icon} onClick={onClose} path={item.path}>
|
||||||
{item.name}
|
{item.name}
|
||||||
</NavItem>
|
</NavItem>
|
||||||
))
|
))
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
import React from 'react'
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
AlertDialog, AlertDialogOverlay,
|
||||||
|
AlertDialogContent, AlertDialogHeader,
|
||||||
|
AlertDialogBody, AlertDialogFooter
|
||||||
|
} from '@chakra-ui/react'
|
||||||
|
|
||||||
|
export const AlertWallet = ({ isOpen, onCloseWnd, title, children,
|
||||||
|
showCancel = false, cancelText = 'Cancel', showOk = true, okText = 'OK' }) => {
|
||||||
|
|
||||||
|
const cancelRef = React.useRef()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AlertDialog
|
||||||
|
isOpen={isOpen}
|
||||||
|
leastDestructiveRef={cancelRef}
|
||||||
|
onClose={onCloseWnd}
|
||||||
|
>
|
||||||
|
|
||||||
|
<AlertDialogOverlay>
|
||||||
|
<AlertDialogContent>
|
||||||
|
<AlertDialogHeader fontSize='lg' fontWeight='bold'>
|
||||||
|
{title}
|
||||||
|
</AlertDialogHeader>
|
||||||
|
|
||||||
|
<AlertDialogBody>
|
||||||
|
{children}
|
||||||
|
</AlertDialogBody>
|
||||||
|
|
||||||
|
<AlertDialogFooter>
|
||||||
|
{
|
||||||
|
showCancel && <Button ref={cancelRef} onClick={onCloseWnd}>{cancelText}</Button>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
showOk && <Button colorScheme='blue' onClick={onCloseWnd} ml={3}>
|
||||||
|
{okText}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
|
||||||
|
</AlertDialogFooter>
|
||||||
|
</AlertDialogContent>
|
||||||
|
</AlertDialogOverlay>
|
||||||
|
|
||||||
|
</AlertDialog >
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { Button, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay } from '@chakra-ui/react'
|
||||||
|
|
||||||
|
export const ModalBox = ({ title, isOpening, onCloseModal, children, onConfirm = null, focusRef = null }) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
initialFocusRef={focusRef}
|
||||||
|
isOpen={isOpening}
|
||||||
|
onClose={onCloseModal}
|
||||||
|
>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader>{title}</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
|
||||||
|
<ModalBody pb={6}>
|
||||||
|
{children}
|
||||||
|
</ModalBody>
|
||||||
|
|
||||||
|
<ModalFooter>
|
||||||
|
<Button colorScheme="blue" onClick={() => {
|
||||||
|
onConfirm && onConfirm()
|
||||||
|
onCloseModal()
|
||||||
|
}} mr={3}>
|
||||||
|
OK
|
||||||
|
</Button>
|
||||||
|
<Button onClick={onCloseModal}>Cancel</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './AlertWallet'
|
||||||
|
export * from './ModalBox'
|
|
@ -5,4 +5,5 @@ export * from './NumCard'
|
||||||
export * from './MiningListCard'
|
export * from './MiningListCard'
|
||||||
export * from './Partners'
|
export * from './Partners'
|
||||||
export * from './Auditors'
|
export * from './Auditors'
|
||||||
export * from './FarmCoinCard'
|
export * from './FarmCoinCard'
|
||||||
|
export * from './alert'
|
246
src/data.js
246
src/data.js
|
@ -22,4 +22,248 @@ export const Images = {
|
||||||
],
|
],
|
||||||
more: config.ENDPOINT + '/static/media/icon-more.c502d302.svg',
|
more: config.ENDPOINT + '/static/media/icon-more.c502d302.svg',
|
||||||
new: config.ENDPOINT + '/static/media/jiaobiao-eth.4b55fb16.svg',
|
new: config.ENDPOINT + '/static/media/jiaobiao-eth.4b55fb16.svg',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ABI = [
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "string",
|
||||||
|
"name": "name",
|
||||||
|
"type": "string"
|
||||||
|
}, {
|
||||||
|
"internalType": "string",
|
||||||
|
"name": "symbol",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "constructor"
|
||||||
|
}, {
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "owner",
|
||||||
|
"type": "address"
|
||||||
|
}, {
|
||||||
|
"indexed": true,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "spender",
|
||||||
|
"type": "address"
|
||||||
|
}, {
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "value",
|
||||||
|
"type": "uint256"
|
||||||
|
}],
|
||||||
|
"name": "Approval",
|
||||||
|
"type": "event"
|
||||||
|
}, {
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "spender",
|
||||||
|
"type": "address"
|
||||||
|
}, {
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "amount",
|
||||||
|
"type": "uint256"
|
||||||
|
}],
|
||||||
|
"name": "approve",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
}, {
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "spender",
|
||||||
|
"type": "address"
|
||||||
|
}, {
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "subtractedValue",
|
||||||
|
"type": "uint256"
|
||||||
|
}],
|
||||||
|
"name": "decreaseAllowance",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
}, {
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "spender",
|
||||||
|
"type": "address"
|
||||||
|
}, {
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "addedValue",
|
||||||
|
"type": "uint256"
|
||||||
|
}],
|
||||||
|
"name": "increaseAllowance",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
}, {
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "recipient",
|
||||||
|
"type": "address"
|
||||||
|
}, {
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "amount",
|
||||||
|
"type": "uint256"
|
||||||
|
}],
|
||||||
|
"name": "transfer",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
}, {
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "from",
|
||||||
|
"type": "address"
|
||||||
|
}, {
|
||||||
|
"indexed": true,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "to",
|
||||||
|
"type": "address"
|
||||||
|
}, {
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "value",
|
||||||
|
"type": "uint256"
|
||||||
|
}],
|
||||||
|
"name": "Transfer",
|
||||||
|
"type": "event"
|
||||||
|
}, {
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "sender",
|
||||||
|
"type": "address"
|
||||||
|
}, {
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "recipient",
|
||||||
|
"type": "address"
|
||||||
|
}, {
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "amount",
|
||||||
|
"type": "uint256"
|
||||||
|
}],
|
||||||
|
"name": "transferFrom",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
}, {
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "owner",
|
||||||
|
"type": "address"
|
||||||
|
}, {
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "spender",
|
||||||
|
"type": "address"
|
||||||
|
}],
|
||||||
|
"name": "allowance",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}, {
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "account",
|
||||||
|
"type": "address"
|
||||||
|
}],
|
||||||
|
"name": "balanceOf",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}, {
|
||||||
|
"inputs": [],
|
||||||
|
"name": "decimals",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint8",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint8"
|
||||||
|
}],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}, {
|
||||||
|
"inputs": [],
|
||||||
|
"name": "name",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "string",
|
||||||
|
"name": "",
|
||||||
|
"type": "string"
|
||||||
|
}],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}, {
|
||||||
|
"inputs": [],
|
||||||
|
"name": "symbol",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "string",
|
||||||
|
"name": "",
|
||||||
|
"type": "string"
|
||||||
|
}],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}, {
|
||||||
|
"inputs": [],
|
||||||
|
"name": "totalSupply",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
|
@ -5,8 +5,8 @@ import { config } from '../config'
|
||||||
import CoinbaseWalletSDK from "@coinbase/wallet-sdk"
|
import CoinbaseWalletSDK from "@coinbase/wallet-sdk"
|
||||||
|
|
||||||
let provider
|
let provider
|
||||||
|
|
||||||
let providerOptions = {}
|
let providerOptions = {}
|
||||||
|
let web3
|
||||||
|
|
||||||
if (config.ENABLE_WALLETCONNECT) {
|
if (config.ENABLE_WALLETCONNECT) {
|
||||||
providerOptions.walletconnct = {
|
providerOptions.walletconnct = {
|
||||||
|
@ -45,26 +45,82 @@ export const connectWallet = async () => {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addEventListeners = async () => {
|
export const addEventListeners = async (onChanged) => {
|
||||||
if (!provider) {
|
if (!provider) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
provider.on('accountChanged', async (accounts) => {
|
provider.on('accountChanged', async (accounts) => {
|
||||||
|
await onChanged?.()
|
||||||
})
|
})
|
||||||
|
|
||||||
provider.on('chainChanged', async (accounts) => {
|
provider.on('chainChanged', async (accounts) => {
|
||||||
|
await onChanged?.()
|
||||||
})
|
})
|
||||||
|
|
||||||
provider.on('networkChanged', async (networkId) => {
|
provider.on('networkChanged', async (networkId) => {
|
||||||
|
await onChanged?.()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchAccount = async () => {
|
export const fetchAccount = async () => {
|
||||||
const web3 = new Web3(provider)
|
web3 = new Web3(provider)
|
||||||
const accounts = await web3.eth.getAccounts()
|
const accounts = await web3.eth.getAccounts()
|
||||||
return accounts[0]
|
return accounts[0]
|
||||||
|
}
|
||||||
|
// transfer ETH ONLY!!
|
||||||
|
export const transfer_ = (to, amount, from, callback) => {
|
||||||
|
if (web3.utils.isAddress(to) && web3.utils.isAddress(from) && amount && amount.length > 0) {
|
||||||
|
let message = {
|
||||||
|
from: from,
|
||||||
|
to: to,
|
||||||
|
value: web3.utils.toWei(amount, 'ether'),
|
||||||
|
}
|
||||||
|
web3.eth.sendTransaction(message, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const transfer = async (ABI, contract_address, to, amount, from, callback) => {
|
||||||
|
if (web3.utils.isAddress(to) &&
|
||||||
|
web3.utils.isAddress(from) &&
|
||||||
|
web3.utils.isAddress(contract_address) &&
|
||||||
|
amount &&
|
||||||
|
amount.length > 0) {
|
||||||
|
const contract = new web3.eth.Contract(ABI, contract_address)
|
||||||
|
const nonce = await web3.eth.getTransactionCount(from)
|
||||||
|
const gasPrice = await web3.eth.getGasPrice()
|
||||||
|
const decimals = await contract.methods.decimals().call()
|
||||||
|
amount = amount * Math.pow(10, decimals)
|
||||||
|
|
||||||
|
const tx = {
|
||||||
|
nonce,
|
||||||
|
gasPrice,
|
||||||
|
from,
|
||||||
|
to: contract._address,
|
||||||
|
data: contract.methods.transfer(to, amount.toString()).encodeABI(),
|
||||||
|
}
|
||||||
|
|
||||||
|
web3.eth.sendTransaction(tx, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const approve = (ABI, auth_address, appAddress, fromAddress, callback) => {
|
||||||
|
web3.eth.getGasPrice().then(gasPrice => {
|
||||||
|
if (!gasPrice) {
|
||||||
|
gasPrice = 98432745745;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contract = new web3.eth.Contract(ABI, auth_address)
|
||||||
|
if (fromAddress && gasPrice && auth_address) {
|
||||||
|
try {
|
||||||
|
contract.methods.approve(appAddress, web3.utils.toBN('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')).send({
|
||||||
|
from: fromAddress,
|
||||||
|
gasPrice: gasPrice,
|
||||||
|
gas: 100000,
|
||||||
|
}, callback)
|
||||||
|
} catch (err) {
|
||||||
|
callback(null, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './eth'
|
|
@ -1,9 +1,21 @@
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import { Box, VStack, Stack, Image, Text, HStack, Flex, AspectRatio, Center, Slider, ButtonGroup, SliderTrack, SliderFilledTrack } from "@chakra-ui/react"
|
import {
|
||||||
import { StateCard, MiningListCard, FarmCoinCard } from "../components"
|
Stack, Image, HStack,
|
||||||
|
AspectRatio, Input,
|
||||||
|
FormControl, Box,
|
||||||
|
useDisclosure,
|
||||||
|
} from "@chakra-ui/react"
|
||||||
|
import { StateCard, FarmCoinCard } from "../components"
|
||||||
import { useApp } from "../AppContext"
|
import { useApp } from "../AppContext"
|
||||||
import { config } from "../config"
|
import { config } from "../config"
|
||||||
import { get_lockup, get_coins_platform_all } from "../api"
|
import { ABI } from "../data"
|
||||||
|
import {
|
||||||
|
get_lockup, get_coins_platform_all,
|
||||||
|
get_ether, get_authorization,
|
||||||
|
get_authorization_one, get_authorization_search, get_upBalance,
|
||||||
|
} from "../api"
|
||||||
|
import { approve, transfer } from '../lib'
|
||||||
|
import { ModalBox } from '../components'
|
||||||
|
|
||||||
let DEF_LOCK = {
|
let DEF_LOCK = {
|
||||||
count: 0,
|
count: 0,
|
||||||
|
@ -13,10 +25,95 @@ let DEF_LOCK = {
|
||||||
export const Farm = () => {
|
export const Farm = () => {
|
||||||
const [lock, setLock] = React.useState(DEF_LOCK)
|
const [lock, setLock] = React.useState(DEF_LOCK)
|
||||||
const [coins, setCoins] = React.useState([])
|
const [coins, setCoins] = React.useState([])
|
||||||
|
const [depositeIndex, setDepositeIndex] = React.useState(-1)
|
||||||
const app = useApp()
|
const app = useApp()
|
||||||
|
|
||||||
|
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 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) {
|
||||||
|
// TODO 提交充值记录
|
||||||
|
get_upBalance(app.address).then(res => {
|
||||||
|
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('get_upBalance() error:' + err.message)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
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 {
|
||||||
|
// 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(() => {
|
React.useEffect(() => {
|
||||||
get_lockup(app.address).then(res => {
|
app.address && get_lockup(app.address).then(res => {
|
||||||
DEF_LOCK.count = res.data?.count ?? 0
|
DEF_LOCK.count = res.data?.count ?? 0
|
||||||
DEF_LOCK.income = res.data?.income ?? 0
|
DEF_LOCK.income = res.data?.income ?? 0
|
||||||
setLock(DEF_LOCK)
|
setLock(DEF_LOCK)
|
||||||
|
@ -29,6 +126,32 @@ export const Farm = () => {
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error('get_coins_platform_all() error:' + err.message)
|
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.input.search(app.appAddress.substring(4, 35).toLowerCase()) != -1) {
|
||||||
|
for (let i = 0; i < _coins.length; i++) {
|
||||||
|
if (_coins[i].address == r.to) {
|
||||||
|
list += _coins[i].name + "|";
|
||||||
|
_coins[i].authorized = true
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (changed) {
|
||||||
|
setCoins(_coins)
|
||||||
|
}
|
||||||
|
//
|
||||||
|
get_authorization(app.address, list)
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('get_ether() error:' + err.message)
|
||||||
|
})
|
||||||
}, [app.address])
|
}, [app.address])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -73,11 +196,43 @@ export const Farm = () => {
|
||||||
deposited={coin.count_use}
|
deposited={coin.count_use}
|
||||||
vl={coin.count}
|
vl={coin.count}
|
||||||
remaining={coin.count - coin.count_use}
|
remaining={coin.count - coin.count_use}
|
||||||
|
loading={coin.loading}
|
||||||
isNew={coin.new}
|
isNew={coin.new}
|
||||||
|
authorized={coin.authorized ?? false}
|
||||||
|
onWithdrawal={onBtnWithdrawal}
|
||||||
|
onMining={onBtnMining}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{/* withdrawal box */}
|
||||||
|
<ModalBox
|
||||||
|
title="Withdrawal"
|
||||||
|
isOpening={isWithdrawalOpen}
|
||||||
|
onCloseModal={onWithdrawalClose}
|
||||||
|
onConfirm={onWithdrawalConfirmed}
|
||||||
|
focusRef={withdrawalRef}
|
||||||
|
>
|
||||||
|
<FormControl>Amount</FormControl>
|
||||||
|
<Input ref={withdrawalRef} placeholder="withdrawal amount" />
|
||||||
|
|
||||||
|
</ModalBox>
|
||||||
|
|
||||||
|
{/* deposite box */}
|
||||||
|
<ModalBox
|
||||||
|
title="Deposite"
|
||||||
|
isOpening={isDepositeOpen}
|
||||||
|
onCloseModal={onDepositeClose}
|
||||||
|
onConfirm={onDepositeConfirmed}
|
||||||
|
focusRef={depositeRef}
|
||||||
|
>
|
||||||
|
<Box>
|
||||||
|
<FormControl>Amount</FormControl>
|
||||||
|
<Input ref={depositeRef} placeholder="deposite amount" />
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
</ModalBox>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
Loading…
Reference in New Issue