diff --git a/config/proxy.ts b/config/proxy.ts index 36d50fc..03d511e 100644 --- a/config/proxy.ts +++ b/config/proxy.ts @@ -11,7 +11,7 @@ export default { // localhost:8000/api/** -> https://preview.pro.ant.design/api/** '/tbg/api/v1': { // 要代理的地址 - target: 'http://192.168.2.11:9999', + target: 'http://192.168.88.238:9999', // 配置了这个可以从 http 代理到 https // 依赖 origin 的功能可能需要这个,比如 cookie changeOrigin: true, diff --git a/dist.zip b/dist.zip new file mode 100644 index 0000000..a1429ac Binary files /dev/null and b/dist.zip differ diff --git a/package.json b/package.json index 14d9265..fc3d41c 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,9 @@ "react-helmet-async": "^1.0.4", "umi": "^3.5.0", "umi-serve": "^1.9.10", - "web3": "^1.7.5" + "web3": "^1.7.5", + "@metamask/detect-provider": "^1.2.0" + }, "devDependencies": { "@ant-design/pro-cli": "^2.0.2", diff --git a/src/access.ts b/src/access.ts index 2ec89bd..774d6c6 100644 --- a/src/access.ts +++ b/src/access.ts @@ -1,9 +1,20 @@ /** * @see https://umijs.org/zh-CN/plugins/plugin-access * */ -export default function access(initialState: { currentUser?: API.CurrentUser | undefined }) { - const { currentUser } = initialState || {}; + +export default function access(initialState: { + currentUser?: API.CurrentUser | undefined; + routeList: any; +}) { + const { currentUser, routeList } = initialState || {}; return { canAdmin: currentUser && currentUser.access === 'admin', + normalRouteFilter: (route: any) => { + return true; + // if (routeList == null || routeList == undefined || routeList.length == 0) { + // return true; + // } + // return routeList.includes(route.name); + }, }; } diff --git a/src/app.tsx b/src/app.tsx index c667cc9..812ea93 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -4,8 +4,19 @@ import { history } from 'umi'; import RightContent from '@/components/RightContent'; import RoutePath from '@/routes/routePath'; import { CACHE_TOKEN } from '@/constants/cacheKey'; +// import { getRoleList } from './services/system/role'; // ProLayout 支持的api https://procomponents.ant.design/components/layout + +// export async function getInitialState() { +// if (localStorage.getItem(CACHE_TOKEN)) { +// const res = await getRoleList({}); +// return { +// routeList: res, +// }; +// } +// } + export const layout: RunTimeLayoutConfig = ({ initialState }) => { return { rightContentRender: () => , diff --git a/src/constants/abi/erc20.json b/src/constants/abi/erc20.json new file mode 100644 index 0000000..8da19b3 --- /dev/null +++ b/src/constants/abi/erc20.json @@ -0,0 +1,196 @@ +[ + { + "inputs": [ + { "internalType": "uint256", "name": "initialSupply", "type": "uint256" }, + { "internalType": "uint8", "name": "initialDecimals", "type": "uint8" }, + { "internalType": "string", "name": "tokenName", "type": "string" }, + { "internalType": "string", "name": "tokenSymbol", "type": "string" } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "sender", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "spender", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "Approval", + "type": "event" + }, + { + "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" + }, + { + "constant": true, + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" } + ], + "name": "allowance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" } + ], + "name": "allowed", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "approve", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "balances", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "uint256", "name": "a", "type": "uint256" }, + { "internalType": "uint256", "name": "b", "type": "uint256" } + ], + "name": "safeAdd", + "outputs": [{ "internalType": "uint256", "name": "c", "type": "uint256" }], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "uint256", "name": "a", "type": "uint256" }, + { "internalType": "uint256", "name": "b", "type": "uint256" } + ], + "name": "safeDiv", + "outputs": [{ "internalType": "uint256", "name": "c", "type": "uint256" }], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "uint256", "name": "a", "type": "uint256" }, + { "internalType": "uint256", "name": "b", "type": "uint256" } + ], + "name": "safeMul", + "outputs": [{ "internalType": "uint256", "name": "c", "type": "uint256" }], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "uint256", "name": "a", "type": "uint256" }, + { "internalType": "uint256", "name": "b", "type": "uint256" } + ], + "name": "safeSub", + "outputs": [{ "internalType": "uint256", "name": "c", "type": "uint256" }], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/constants/enum/contract.ts b/src/constants/enum/contract.ts new file mode 100644 index 0000000..e0cb7f9 --- /dev/null +++ b/src/constants/enum/contract.ts @@ -0,0 +1,4 @@ +export enum ContractType { + ERC20 = '20', + NFT721 = '721', +} diff --git a/src/constants/enum/notice.ts b/src/constants/enum/notice.ts new file mode 100644 index 0000000..f87bf01 --- /dev/null +++ b/src/constants/enum/notice.ts @@ -0,0 +1,7 @@ +export enum NoticeType { + RECHARGE = 10000, + WITHDRAW = 20000, + NFTCREATE = 30000, + NFTTRANSFER = 30010, + NFTTDISPOSE = 30020, +} diff --git a/src/constants/enum/withdraw.ts b/src/constants/enum/withdraw.ts new file mode 100644 index 0000000..12464c1 --- /dev/null +++ b/src/constants/enum/withdraw.ts @@ -0,0 +1,5 @@ +export enum WithdrawType { + SUCCESS = 10000, + FAILED = 20000, + PENDDING = 30000, +} diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx index f876e6e..5152408 100644 --- a/src/pages/Login/index.tsx +++ b/src/pages/Login/index.tsx @@ -6,10 +6,11 @@ import { login } from '@/services/login'; import defaultSettings from '../../../config/defaultSettings'; import styles from './index.less'; import { CACHE_TOKEN } from '@/constants/cacheKey'; +import access from '@/access'; const Login: React.FC = () => { const intl = useIntl(); - + const { initialState, refresh } = useModel('@@initialState'); const handleSubmit = async (values: API.LoginParams) => { // 登录 const res: any = await login({ ...values }); @@ -19,6 +20,8 @@ const Login: React.FC = () => { const { query } = history.location; const { redirect } = query as { redirect: string }; history.push(redirect || '/'); + refresh(); + access(initialState); }; return ( diff --git a/src/pages/Nft/NftContract/List/components/AddNftContract.tsx b/src/pages/Nft/NftContract/List/components/AddNftContract.tsx index 473de75..2367fd2 100644 --- a/src/pages/Nft/NftContract/List/components/AddNftContract.tsx +++ b/src/pages/Nft/NftContract/List/components/AddNftContract.tsx @@ -22,8 +22,10 @@ const form = createForm({}); const AddNftContractModal = ({ onOk, onCancel, ...rest }: AddNftContractModalPropsType) => { const handleOk = () => { - const formState = form.getFormState(); - onOk(formState.values); + form.submit(async () => { + const formState = form.getFormState(); + onOk(formState.values); + }); }; const handleCancel = () => { onCancel(); @@ -34,25 +36,25 @@ const AddNftContractModal = ({ onOk, onCancel, ...rest }: AddNftContractModalPro
- -
diff --git a/src/pages/Nft/NftContract/List/index.tsx b/src/pages/Nft/NftContract/List/index.tsx index 7f8ec80..db26c55 100644 --- a/src/pages/Nft/NftContract/List/index.tsx +++ b/src/pages/Nft/NftContract/List/index.tsx @@ -1,32 +1,42 @@ -import React, { useRef, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import Table, { ProColumns, ActionType } from '@/components/Table'; import { message } from 'antd'; -// import { fetchTableData } from '@/utils/table'; import AddNftContractModal from './components/AddNftContract'; +import { getContractInfo } from '@/services/contract'; +import { ContractType } from '@/constants/enum/contract'; +import { deployContract, initWeb3 } from '@/utils/web3'; +import { createNFTContract, getNFTContractList } from '@/services/nft'; +import { fetchTableData } from '@/utils/table'; const Address: React.FC = () => { const tableRef = useRef(); - const [NftModal, setNftModal] = useState(false); const [visible, setVisible] = useState(false); + const [contractData, setContractData] = useState({}); const columns: ProColumns[] = [ { title: '合约名称', - dataIndex: 'time', - width: '10%', + dataIndex: 'token_name', + width: '15%', + hideInSearch: true, + }, + { + title: '合约单位', + dataIndex: 'token_symbol', + width: '15%', hideInSearch: true, }, { title: '合约地址', dataIndex: 'address', hideInSearch: true, - width: '20%', + width: '50%', }, { - title: 'NFT数量', - dataIndex: 'nft_num', - width: 150, + title: '描述', + dataIndex: 'description', hideInSearch: true, + ellipsis: true, }, ]; @@ -35,30 +45,44 @@ const Address: React.FC = () => { { - setVisible(true); + onConfirm: async () => { + const res = await getContractInfo({ erc: ContractType.NFT721 }); + if (res.bin != '') { + setContractData(res); + setVisible(true); + } else { + message.success('已有NFT合约'); + } }, }, ]} - // request={async (params) => { - // // return fetchTableData(, params); - // }} + request={async (params) => { + const res = await fetchTableData(getNFTContractList, params); + return res; + }} /> { try { - const params = { ...val }; - // await creatNftAddress(params); + await initWeb3(); + const res = await deployContract(contractData.abi, contractData.bin, [ + val.token_name, + val.token_symbol, + ]); + val.address = res; + await createNFTContract(val); message.success('添加成功'); + setVisible(false); } catch (e) { console.log(e); message.success('发生错误'); diff --git a/src/pages/Nft/NftToken/List/components/AddNftModel.tsx b/src/pages/Nft/NftToken/List/components/AddNftModel.tsx index f9b0cdd..6b3a054 100644 --- a/src/pages/Nft/NftToken/List/components/AddNftModel.tsx +++ b/src/pages/Nft/NftToken/List/components/AddNftModel.tsx @@ -22,8 +22,10 @@ const form = createForm({}); const AddNftModal = ({ onOk, onCancel, ...rest }: AddNftModalPropsType) => { const handleOk = () => { - const formState = form.getFormState(); - onOk(formState.values); + form.submit(() => { + const formState = form.getFormState(); + onOk(formState.values); + }); }; const handleCancel = () => { onCancel(); @@ -33,33 +35,45 @@ const AddNftModal = ({ onOk, onCancel, ...rest }: AddNftModalPropsType) => {
+ + - - + - diff --git a/src/pages/Nft/NftToken/List/components/TransferNFTModel.tsx b/src/pages/Nft/NftToken/List/components/TransferNFTModel.tsx new file mode 100644 index 0000000..df4d708 --- /dev/null +++ b/src/pages/Nft/NftToken/List/components/TransferNFTModel.tsx @@ -0,0 +1,58 @@ +import React, { useRef } from 'react'; +import { createForm } from '@formily/core'; +import { createSchemaField } from '@formily/react'; +import Modal, { ModalProps } from '@/components/Modal'; +// import { fetchTableData } from '@/utils/table'; +import { Form, FormItem, Input, NumberPicker } from '@formily/antd'; + +interface TransferNFTModelPropsType extends ModalProps { + onOk: (val: any) => void; + onCancel: () => void; +} + +const SchemaField = createSchemaField({ + components: { + FormItem, + Input, + NumberPicker, + }, +}); + +const form = createForm({}); + +const TransferNFTModel = ({ onOk, onCancel, ...rest }: TransferNFTModelPropsType) => { + const handleOk = async () => { + form.submit(async () => { + const formState = form.getFormState(); + onOk(formState.values); + }); + }; + const handleCancel = () => { + onCancel(); + }; + + return ( + +
+ + + + + +
+ ); +}; + +export default TransferNFTModel; diff --git a/src/pages/Nft/NftToken/List/index.tsx b/src/pages/Nft/NftToken/List/index.tsx index 47dfe66..e3724dd 100644 --- a/src/pages/Nft/NftToken/List/index.tsx +++ b/src/pages/Nft/NftToken/List/index.tsx @@ -1,34 +1,49 @@ import React, { useRef, useState } from 'react'; import Table, { ProColumns, ActionType } from '@/components/Table'; import { message } from 'antd'; -// import { fetchTableData } from '@/utils/table'; - +import { fetchTableData } from '@/utils/table'; import AddNftModal from './components/AddNftModel'; -import PaySelectModal from '@/widget/PaySelectModal'; +import { initWeb3, NFTMint } from '@/utils/web3'; +import { getContractInfo } from '@/services/contract'; +import { ContractType } from '@/constants/enum/contract'; +import { checkTokenId, getNFTContractList, getNFTList, mintNFT } from '@/services/nft'; const Address: React.FC = () => { const tableRef = useRef(); - const [NftModal, setNftModal] = useState(false); const [visible, setVisible] = useState(false); - const [payVisible, setPayVisible] = useState(false); const columns: ProColumns[] = [ { - title: '合约名称', - dataIndex: 'time', + title: 'TokenId', + dataIndex: 'token_id', width: '10%', hideInSearch: true, }, { - title: 'NFT名称', + title: '所有者地址', dataIndex: 'address', hideInSearch: true, - width: '20%', }, { - title: 'TokenId', - dataIndex: 'token_id', - width: 150, + title: 'NFT名称', + dataIndex: 'name', + hideInSearch: true, + }, + { + title: '图片', + dataIndex: 'image', + hideInSearch: true, + ellipsis: true, + }, + { + title: '缩略图', + dataIndex: 'avatar', + hideInSearch: true, + ellipsis: true, + }, + { + title: '描述', + dataIndex: 'description', hideInSearch: true, }, ]; @@ -38,6 +53,7 @@ const Address: React.FC = () => {
{ setVisible(true); }, }, - { - type: 'add', - text: '分发NFT', - onConfirm: () => { - setNftModal(true); - }, - }, ]} - // request={async (params) => { - // // return fetchTableData(, params); - // }} + request={async (params) => { + const res = await fetchTableData(getNFTList, params); + return res; + }} /> { setVisible(false); }} onOk={async function (val: any): Promise { - try { - const params = { ...val }; - // await creatNftAddress(params); - message.success('添加成功'); - } catch (e) { - console.log(e); - message.success('发生错误'); - setVisible(false); - } - }} - /> - { - try { - const params = { ...val }; - // await creatNftAddress(params); - console.log(params); - message.success('添加成功'); - } catch (e) { - console.log(e); - message.success('发生错误'); - setVisible(false); - } - }} /> ); diff --git a/src/pages/Nft/NftTrade/List/index.tsx b/src/pages/Nft/NftTrade/List/index.tsx new file mode 100644 index 0000000..c619fde --- /dev/null +++ b/src/pages/Nft/NftTrade/List/index.tsx @@ -0,0 +1,81 @@ +import React, { useRef } from 'react'; +import Table, { ProColumns, ActionType } from '@/components/Table'; +import { getRecordList } from '@/services/recharge/record'; +import { fetchTableData } from '@/utils/table'; +import moment from 'moment'; +import { ContractType } from '@/constants/enum/contract'; + +const NFTTradeList = () => { + const tableRef = useRef(); + const columns: ProColumns[] = [ + { + title: '时间', + dataIndex: 'time', + hideInTable: true, + valueType: 'dateRange', + ellipsis: true, + }, + { + title: '交易哈希', + dataIndex: 'tx_hash', + hideInSearch: true, + ellipsis: true, + }, + { + title: 'TokenID', + dataIndex: 'token_id', + width: '10%', + hideInSearch: true, + }, + { + title: '块编号', + dataIndex: 'block_number', + hideInSearch: true, + }, + { + title: '发送地址', + dataIndex: 'from_address', + hideInSearch: true, + ellipsis: true, + }, + { + title: '接受地址', + dataIndex: 'to_address', + hideInSearch: true, + ellipsis: true, + }, + { + title: '充值时间', + dataIndex: 'time', + hideInSearch: true, + ellipsis: true, + }, + ]; + return ( +
{ + console.log('params = ', params); + if ((params.time ?? '') !== '') { + const start = Date.parse(params.time[0] + ' 00:00:00'); + const end = Date.parse(params.time[1] + ' 23:59:59'); + params.start_time = start / 1000; + params.end_time = end / 1000; + } + params.erc = ContractType.NFT721; + const res = await fetchTableData(getRecordList, params); + for (const key in res.data) { + if (Object.prototype.hasOwnProperty.call(res.data, key)) { + const element = res.data[key]; + element.time = moment(element.time * 1000).format('YYYY-MM-DD hh:mm:ss'); + } + } + return res; + }} + /> + ); +}; + +export default NFTTradeList; diff --git a/src/pages/Recharge/CoinType/List/index.tsx b/src/pages/Recharge/CoinType/List/index.tsx index c860f7b..625b07f 100644 --- a/src/pages/Recharge/CoinType/List/index.tsx +++ b/src/pages/Recharge/CoinType/List/index.tsx @@ -1,9 +1,12 @@ import React, { useState, useRef } from 'react'; import Table, { ProColumns, ActionType } from '@/components/Table'; import { addCoinType, getCoinTypeList, modifyCoinType } from '@/services/recharge/coinType'; +import { getContractInfo } from '@/services/contract'; import { fetchTableData } from '@/utils/table'; import AddCoinTypeModal from '../components/AddCoinTypeModal'; import EditCoinTypeModal from '../components/EditCoinTypeModal'; +import { initWeb3, deployContract, transfer } from '@/utils/web3'; +import { ContractType } from '@/constants/enum/contract'; const CoinTypeList = () => { const tableRef = useRef(); @@ -39,7 +42,7 @@ const CoinTypeList = () => { }, { title: '代币发行总量', - dataIndex: 'num', + dataIndex: 'total', hideInSearch: true, ellipsis: true, }, @@ -64,6 +67,7 @@ const CoinTypeList = () => {
{ setIsModalVisible(false); }} onOk={async function (val: any): Promise { + const res = await getContractInfo({ erc: ContractType.ERC20 }); + await initWeb3(); + const result = await deployContract(res.abi, res.bin, [ + val.num, + val.tokenName, + val.tokenSymbol, + ]); + val.address = result; await addCoinType(val); setIsModalVisible(false); tableRef.current?.reload(); diff --git a/src/pages/Recharge/CoinType/components/AddCoinTypeModal.tsx b/src/pages/Recharge/CoinType/components/AddCoinTypeModal.tsx index 8891508..deebe59 100644 --- a/src/pages/Recharge/CoinType/components/AddCoinTypeModal.tsx +++ b/src/pages/Recharge/CoinType/components/AddCoinTypeModal.tsx @@ -21,9 +21,11 @@ const SchemaField = createSchemaField({ const form = createForm({}); const AddCoinTypeModal = ({ onOk, onCancel, ...rest }: AddCoinTypeModalPropsType) => { - const handleOk = () => { - const formState = form.getFormState(); - onOk(formState.values); + const handleOk = async () => { + form.submit(async () => { + const formState = form.getFormState(); + onOk(formState.values); + }); }; const handleCancel = () => { @@ -36,21 +38,35 @@ const AddCoinTypeModal = ({ onOk, onCancel, ...rest }: AddCoinTypeModalPropsType + + + - { - const formState = form.getFormState(); - onOk(formState.values); + form.submit(async () => { + const formState = form.getFormState(); + onOk(formState.values); + }); }; const handleCancel = () => { @@ -51,17 +53,17 @@ const EditCoinTypeModal = ({ x-decorator="FormItem" x-component="Input" /> - - diff --git a/src/pages/Recharge/Record/List/index.tsx b/src/pages/Recharge/Record/List/index.tsx index 64449c3..a0210e2 100644 --- a/src/pages/Recharge/Record/List/index.tsx +++ b/src/pages/Recharge/Record/List/index.tsx @@ -2,9 +2,8 @@ import React, { useRef } from 'react'; import Table, { ProColumns, ActionType } from '@/components/Table'; import { getRecordList } from '@/services/recharge/record'; import { fetchTableData } from '@/utils/table'; -import { getBalanceAmount } from '@/utils/formatBalance'; -import BigNumber from 'bignumber.js'; import moment from 'moment'; +import { ContractType } from '@/constants/enum/contract'; const RecordList = () => { const tableRef = useRef(); @@ -28,12 +27,6 @@ const RecordList = () => { width: '10%', hideInSearch: true, }, - { - title: '位数', - dataIndex: 'decimals', - width: '10%', - hideInSearch: true, - }, { title: '游戏币类型', dataIndex: 'name', @@ -62,25 +55,20 @@ const RecordList = () => { return (
{ - console.log('params = ', params); if ((params.time ?? '') !== '') { const start = Date.parse(params.time[0] + ' 00:00:00'); const end = Date.parse(params.time[1] + ' 23:59:59'); params.start_time = start / 1000; params.end_time = end / 1000; } + params.erc = ContractType.ERC20; const res = await fetchTableData(getRecordList, params); - console.log('res = ', res); for (const key in res.data) { if (Object.prototype.hasOwnProperty.call(res.data, key)) { const element = res.data[key]; - element.price = getBalanceAmount( - new BigNumber(element.price), - element.decimals, - ).toNumber(); element.time = moment(element.time * 1000).format('YYYY-MM-DD hh:mm:ss'); } } diff --git a/src/pages/Recharge/Wallet/List/index.tsx b/src/pages/Recharge/Wallet/List/index.tsx index 5a5177d..57ac079 100644 --- a/src/pages/Recharge/Wallet/List/index.tsx +++ b/src/pages/Recharge/Wallet/List/index.tsx @@ -41,7 +41,6 @@ const CollectionAddressList = () => { title: '收款游戏币名称', dataIndex: 'name', hideInSearch: true, - ellipsis: true, }, { title: '操作', diff --git a/src/pages/Recharge/Wallet/components/AddWalletModal.tsx b/src/pages/Recharge/Wallet/components/AddWalletModal.tsx index c043339..76d06c0 100644 --- a/src/pages/Recharge/Wallet/components/AddWalletModal.tsx +++ b/src/pages/Recharge/Wallet/components/AddWalletModal.tsx @@ -37,7 +37,7 @@ const form = createForm({ effects: () => { // eslint-disable-next-line react-hooks/rules-of-hooks useAsyncDataSource('name', async (field) => { - const list = await getCoinTypeList({ page: 1, page_size: 10 }); + const list = await getCoinTypeList({ page: 1, size: 10 }); const option = []; for (let index = 0; index < list.items.length; index++) { const element = list.items[index]; @@ -54,8 +54,10 @@ const form = createForm({ const AddWalletModal = ({ onOk, onCancel, ...rest }: AddWalletModalPropsType) => { const handleOk = () => { - const formState = form.getFormState(); - onOk(formState.values); + form.submit(async () => { + const formState = form.getFormState(); + onOk(formState.values); + }); }; const handleCancel = () => { diff --git a/src/pages/Recharge/Wallet/components/EditWalletModal.tsx b/src/pages/Recharge/Wallet/components/EditWalletModal.tsx index 11632bd..9477457 100644 --- a/src/pages/Recharge/Wallet/components/EditWalletModal.tsx +++ b/src/pages/Recharge/Wallet/components/EditWalletModal.tsx @@ -39,7 +39,7 @@ const EditWalletModal = ({ onOk, onCancel, editModalData, ...rest }: EditWalletM effects: () => { // eslint-disable-next-line react-hooks/rules-of-hooks useAsyncDataSource('name', async (field) => { - const list = await getCoinTypeList({ page: 1, page_size: 10 }); + const list = await getCoinTypeList({ page: 1, size: 10 }); const option = []; for (let index = 0; index < list.items.length; index++) { const element = list.items[index]; @@ -59,8 +59,10 @@ const EditWalletModal = ({ onOk, onCancel, editModalData, ...rest }: EditWalletM }); const handleOk = () => { - const formState = form.getFormState(); - onOk(formState.values); + form.submit(async () => { + const formState = form.getFormState(); + onOk(formState.values); + }); }; const handleCancel = () => { diff --git a/src/pages/Recharge/Withdraw/List/index.tsx b/src/pages/Recharge/Withdraw/List/index.tsx index 79dfe61..e76a2d2 100644 --- a/src/pages/Recharge/Withdraw/List/index.tsx +++ b/src/pages/Recharge/Withdraw/List/index.tsx @@ -2,16 +2,33 @@ import React, { useRef } from 'react'; import Table, { ProColumns, ActionType } from '@/components/Table'; import { getWithdrawList, solveWithdraw } from '@/services/recharge/withdraw'; import { fetchTableData } from '@/utils/table'; -import { getBalanceAmount } from '@/utils/formatBalance'; -import BigNumber from 'bignumber.js'; import ConfirmButton from '@/components/Table/ConfirmButton'; import moment from 'moment'; +import { WithdrawType } from '@/constants/enum/withdraw'; const WithdrawList = () => { const handleConfirm = async (uuid) => { await solveWithdraw({ uuid: uuid }); }; + const WithdrawTypeList = [ + { + label: '成功', + value: WithdrawType.SUCCESS, + status: 'Success', + }, + { + label: '失败', + value: WithdrawType.FAILED, + status: 'Error', + }, + { + label: '待处理', + value: WithdrawType.PENDDING, + status: 'Warning', + }, + ]; + const tableRef = useRef(); const columns: ProColumns[] = [ { @@ -36,6 +53,18 @@ const WithdrawList = () => { dataIndex: 'type', width: '10%', }, + { + title: '状态', + dataIndex: 'status', + width: '10%', + valueEnum: () => { + const options = {}; + WithdrawTypeList.forEach((item) => { + options[item.value] = { text: item.label, status: item.status }; + }); + return options; + }, + }, { title: '时间', dataIndex: 'time', @@ -69,10 +98,6 @@ const WithdrawList = () => { for (const key in res.data) { if (Object.prototype.hasOwnProperty.call(res.data, key)) { const element = res.data[key]; - element.price = getBalanceAmount( - new BigNumber(element.price), - element.decimals, - ).toNumber(); element.time = moment(element.time * 1000).format('YYYY-MM-DD hh:mm:ss'); } } diff --git a/src/pages/System/Account/List/index.tsx b/src/pages/System/Account/List/index.tsx index b6e98c7..8776c1e 100644 --- a/src/pages/System/Account/List/index.tsx +++ b/src/pages/System/Account/List/index.tsx @@ -74,7 +74,8 @@ const AccountManageList = () => {
void; @@ -15,13 +16,15 @@ const SchemaField = createSchemaField({ components: { FormItem, Input, - Select, + TreeSelect, }, }); const form = createForm({}); const AddAccountModal = ({ onOk, onCancel, ...rest }: AddAccountModalPropsType) => { + const [treeData, setTreeData] = useState({}); + const handleOk = async () => { form.submit(async () => { onOk(); @@ -35,6 +38,30 @@ const AddAccountModal = ({ onOk, onCancel, ...rest }: AddAccountModalPropsType) onCancel(); }; + const onChange = (newValue: string[]) => {}; + + useEffect(() => { + const array = routes; + array.forEach((item: any, index) => { + if (item.name == '' || item.name == null || item.name == undefined) { + array.splice(index, 1); + console.log('array.splice(index, 1);'); + } + item.key = index + 1; + if (Object.prototype.hasOwnProperty.call(item, 'routes')) { + item.routes?.forEach((item2: any, index2: number) => { + if (item2.name == '' || item2.name == null || item2.name == undefined) { + item.routes.splice(index2, 1); + console.log('item.routes.splice(index2, 1);'); + } + item2.key = parseInt(index + 1 + '' + index2); + }); + } + }); + console.log('array = ', array); + setTreeData(array); + }, []); + return (
@@ -64,15 +91,19 @@ const AddAccountModal = ({ onOk, onCancel, ...rest }: AddAccountModalPropsType) /> diff --git a/src/pages/System/Account/components/EditAccountModal.tsx b/src/pages/System/Account/components/EditAccountModal.tsx index 44f66ba..4c72ce0 100644 --- a/src/pages/System/Account/components/EditAccountModal.tsx +++ b/src/pages/System/Account/components/EditAccountModal.tsx @@ -28,10 +28,12 @@ const AddUserModal = ({ onOk, onCancel, editModalData, ...rest }: AddUserModalPr }); const handleOk = async () => { - onOk(); - const formState = form.getFormState(); - formState.values.role = parseInt(formState.values.role); - await updateUser(formState.values); + form.submit(async () => { + onOk(); + const formState = form.getFormState(); + formState.values.role = parseInt(formState.values.role); + await addUser(formState.values); + }); }; const handleCancel = () => { diff --git a/src/pages/System/Notice/List/index.tsx b/src/pages/System/Notice/List/index.tsx index 46b3abf..db3f855 100644 --- a/src/pages/System/Notice/List/index.tsx +++ b/src/pages/System/Notice/List/index.tsx @@ -6,6 +6,7 @@ import DeleteButton from '@/components/Table/DeleteButton'; import { Switch } from 'antd'; import AddNoticeModal from '../components/AddNoticeModal'; import EditNoticeModal from '../components/EditNoticeModal'; +import { NoticeType } from '@/constants/enum/notice'; const NoticeList = () => { const tableRef = useRef(); @@ -25,12 +26,40 @@ const NoticeList = () => { tableRef.current?.reload(); }; + const noticeTypeList = [ + { + label: '充值', + value: NoticeType.RECHARGE, + }, + { + label: '提现', + value: NoticeType.WITHDRAW, + }, + { + label: 'NFT创建', + value: NoticeType.NFTCREATE, + }, + { + label: 'NFT转移', + value: NoticeType.NFTTRANSFER, + }, + { + label: 'NFT销毁', + value: NoticeType.NFTTDISPOSE, + }, + ]; + const columns: ProColumns[] = [ { title: '通知码', dataIndex: 'code', - hideInSearch: true, - ellipsis: true, + valueEnum: () => { + const options = {}; + noticeTypeList.forEach((item) => { + options[item.value] = item.label; + }); + return options; + }, }, { title: '通知地址', @@ -74,6 +103,7 @@ const NoticeList = () => {
void; onCancel: () => void; @@ -22,9 +47,11 @@ const form = createForm({}); const AddNoticeModal = ({ onOk, onCancel, ...rest }: AddNoticeModalPropsType) => { const handleOk = () => { - const formState = form.getFormState(); - formState.values.code = parseInt(formState.values.code); - onOk(formState.values); + form.submit(async () => { + const formState = form.getFormState(); + formState.values.code = parseInt(formState.values.code); + onOk(formState.values); + }); }; const handleCancel = () => { @@ -35,12 +62,15 @@ const AddNoticeModal = ({ onOk, onCancel, ...rest }: AddNoticeModalPropsType) => - { - const formState = form.getFormState(); - onOk(formState.values); + form.submit(async () => { + const formState = form.getFormState(); + onOk(formState.values); + }); }; const handleCancel = () => { diff --git a/src/pages/System/Permissions/List/index.tsx b/src/pages/System/Permissions/List/index.tsx index 4bf8b7a..68a9d00 100644 --- a/src/pages/System/Permissions/List/index.tsx +++ b/src/pages/System/Permissions/List/index.tsx @@ -1,62 +1,54 @@ import React, { useState, useRef } from 'react'; import Table, { ProColumns, ActionType } from '@/components/Table'; -import { fetchTableData } from '@/utils/table'; -import DeleteButton from '@/components/Table/DeleteButton'; +import routes from '@/routes'; const PermissionsList = () => { - const handleEdit = (row: any) => {}; - - const handleDelete = async (name: any) => {}; const tableRef = useRef(); const columns: ProColumns[] = [ { - title: '收款地址', - dataIndex: 'address', - hideInSearch: true, - ellipsis: true, - }, - { - title: '收款游戏币类型', - dataIndex: 'type', - hideInSearch: true, - ellipsis: true, - }, - { - title: '操作', - valueType: 'option', - width: 150, - render: (_, row) => [ - { - handleEdit(row); - }} - > - 编辑 - , - { - handleDelete(row.name); - }} - />, - ], + title: '路由名称', + dataIndex: 'name', }, ]; + const rowSelection = { + onChange: (selectedRowKeys: React.Key[], selectedRows: DataType[]) => { + console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows); + }, + }; return (
{}, - }, - ]} + search={false} + // rowKey="key" + // childrenColumnName="routes" + rowSelection={{ + ...rowSelection, + }} + // toolBarActions={[ + // { + // type: 'add', + // onConfirm: () => {}, + // }, + // ]} actionRef={tableRef} request={async (params) => { - return {}; + const array = routes; + array.forEach((item: any, index) => { + if (item.name == '' || item.name == null || item.name == undefined) { + array.splice(index, 1); + } + item.key = index + 1; + if (Object.prototype.hasOwnProperty.call(item, 'routes')) { + item.routes?.forEach((item2: any, index2: number) => { + if (item2.name == '' || item2.name == null || item2.name == undefined) { + item.routes.splice(index2, 1); + } + item2.key = parseInt(index + 1 + '' + index2); + }); + } + }); + return { data: array }; }} /> diff --git a/src/pages/User/List/index.tsx b/src/pages/User/List/index.tsx index 0b61757..61bdf83 100644 --- a/src/pages/User/List/index.tsx +++ b/src/pages/User/List/index.tsx @@ -7,7 +7,7 @@ const UserManageList = () => { const tableRef = useRef(); const columns: ProColumns[] = [ { - title: '用户钱包地址', + title: '钱包地址', dataIndex: 'address', ellipsis: true, }, @@ -22,12 +22,6 @@ const UserManageList = () => {
{}, - }, - ]} actionRef={tableRef} request={async (params) => { const res = await fetchTableData(getUserList, params); diff --git a/src/routes/index.ts b/src/routes/index.ts index 184eaa6..20737af 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -13,6 +13,7 @@ export default [ { name: '充值系统', path: RoutePath.RECHARGE, + access: 'normalRouteFilter', routes: [ { path: RoutePath.RECHARGE, @@ -22,21 +23,25 @@ export default [ { name: '充值订单', path: RoutePath.RECORD.LIST, + access: 'normalRouteFilter', component: './Recharge/Record/List', }, { name: '收款地址', path: RoutePath.WALLET.LIST, + access: 'normalRouteFilter', component: './Recharge/Wallet/List', }, { name: '代币种类', path: RoutePath.COIN_TYPE.LIST, + access: 'normalRouteFilter', component: './Recharge/CoinType/List', }, { name: '提现管理', path: RoutePath.WITHDRAW.LIST, + access: 'normalRouteFilter', component: './Recharge/Withdraw/List', }, ], @@ -44,6 +49,7 @@ export default [ { name: '用户账号', path: RoutePath.USER, + access: 'normalRouteFilter', routes: [ { path: RoutePath.USER, @@ -53,6 +59,7 @@ export default [ { name: '用户账号管理', path: RoutePath.USER_LIST.LIST, + access: 'normalRouteFilter', component: './User/List', }, ], @@ -60,6 +67,7 @@ export default [ { name: '系统设置', path: RoutePath.SYSTEM, + access: 'normalRouteFilter', routes: [ { path: RoutePath.SYSTEM, @@ -69,32 +77,38 @@ export default [ { name: '账号管理', path: RoutePath.ACCOUNT.LIST, + access: 'normalRouteFilter', component: './System/Account/List', }, { name: '角色管理', path: RoutePath.ROLE.LIST, + access: 'normalRouteFilter', component: './System/Role/List', }, { name: '权限管理', path: RoutePath.PERMISSIONS.LIST, + access: 'normalRouteFilter', component: './System/Permissions/List', }, { name: '通知管理', path: RoutePath.NOTICE.LIST, + access: 'normalRouteFilter', component: './System/Notice/List', }, { name: '密钥管理', path: RoutePath.SECRET_KEY, + access: 'normalRouteFilter', component: './System/SecretKey', }, ], }, { name: '数据看板', + access: 'normalRouteFilter', path: RoutePath.DATABOARD, routes: [ { @@ -105,21 +119,25 @@ export default [ { name: '核心看板', path: RoutePath.COREDATA.LIST, + access: 'normalRouteFilter', component: './DataBoard/CoreData/List', }, { name: '活跃分析', path: RoutePath.ACTIVEANALYSIS.LIST, + access: 'normalRouteFilter', component: './DataBoard/ActiveAnalysis/List', }, { name: '留存分析', path: RoutePath.RETENTIONANALYSIS.LIST, + access: 'normalRouteFilter', component: './DataBoard/RetentionAnalysis/List', }, { name: '用户充值分析', path: RoutePath.RECHARGEANALYSIS.LIST, + access: 'normalRouteFilter', component: './DataBoard/RechargeAnalysis/List', }, ], @@ -127,6 +145,7 @@ export default [ { name: 'NFT', path: RoutePath.NFT, + access: 'normalRouteFilter', routes: [ { path: RoutePath.NFT, @@ -136,13 +155,21 @@ export default [ { name: 'NFT合约管理', path: RoutePath.NFTCONTRACT.LIST, + access: 'normalRouteFilter', component: './NFT/NftContract/List', }, { name: 'NFT管理', path: RoutePath.NFTTOKEN.LIST, + access: 'normalRouteFilter', component: './NFT/NftToken/List', }, + { + name: 'NFT交易', + path: RoutePath.NFTTRADE.LIST, + access: 'normalRouteFilter', + component: './NFT/NftTrade/List', + }, ], }, { diff --git a/src/routes/routePath.ts b/src/routes/routePath.ts index 5791660..043a59b 100644 --- a/src/routes/routePath.ts +++ b/src/routes/routePath.ts @@ -43,6 +43,9 @@ const RoutePath = { NFTTOKEN: { LIST: `${NFT}/nfttoken`, }, + NFTTRADE: { + LIST: `${NFT}/NFT_trade`, + }, DATABOARD: DATABOARD, COREDATA: { LIST: `${DATABOARD}/coredata`, diff --git a/src/services/contract.ts b/src/services/contract.ts new file mode 100644 index 0000000..81626f8 --- /dev/null +++ b/src/services/contract.ts @@ -0,0 +1,15 @@ +import request from '@/utils/request'; + +/** + * 获取合约 + * @param {object} params + * erc 合约类型 + * @returns {object} data + */ +export const getContractInfo = (data) => { + return request.request({ + url: '/contract/get', + method: 'post', + data, + }); +}; diff --git a/src/services/nft.ts b/src/services/nft.ts new file mode 100644 index 0000000..b3ac4fd --- /dev/null +++ b/src/services/nft.ts @@ -0,0 +1,87 @@ +import request from '@/utils/request'; + +/** + * 获取NFT合约列表 + * @param {object} params + * @returns {array} data + * name 游戏币名称 + * type 游戏币类型 + * usdt_price 游戏货币与usdt的比例 + * eth_price 游戏货币与eth的比例 + */ +export const getNFTContractList = () => { + return request.request({ + url: '/erc721/get', + method: 'get', + }); +}; + +/** + * 创建NFT合约 + * @param {object} data + * + * @returns {array} data + */ +export const createNFTContract = (data) => { + return request.request({ + url: '/erc721/create', + method: 'post', + data, + }); +}; + +/** + * 查询token_Id是否存在 + * @param {object} params + * + * @returns {array} data + */ +export const checkTokenId = (params) => { + return request.request({ + url: '/nft/check', + method: 'get', + params, + }); +}; + +/** + * 获取NFT列表 + * @param {object} params + * + * @returns {array} data + */ +export const getNFTList = (params) => { + return request.request({ + url: '/nft/get', + method: 'get', + params, + }); +}; + +/** + * mintNFT + * @param {object} data + * + * @returns {array} data + */ +export const mintNFT = (data) => { + return request.request({ + url: '/nft/create', + method: 'post', + data, + }); +}; + +/** + * 更新NFT信息 + * @param {object} data + * + * @returns {array} data + */ +export const updateNFTInfo = (data) => { + return request.request({ + url: '/nft/update', + method: 'post', + data, + }); +}; diff --git a/src/services/recharge/coinType.ts b/src/services/recharge/coinType.ts index f8835df..1035174 100644 --- a/src/services/recharge/coinType.ts +++ b/src/services/recharge/coinType.ts @@ -4,7 +4,7 @@ import request from '@/utils/request'; * 获取代币种类列表 * @param {object} params * type 代币种类 - * @returns {array} data + * @returns {array} dat * name 游戏币名称 * type 游戏币类型 * usdt_price 游戏货币与usdt的比例 @@ -12,7 +12,7 @@ import request from '@/utils/request'; */ export const getCoinTypeList = (params) => { return request.request({ - url: '/token/get', + url: '/erc20/get', method: 'get', params, }); @@ -29,7 +29,7 @@ export const getCoinTypeList = (params) => { */ export const addCoinType = (data) => { return request.request({ - url: '/token/create', + url: '/erc20/create', method: 'post', data, }); @@ -46,7 +46,7 @@ export const addCoinType = (data) => { */ export const modifyCoinType = (data) => { return request.request({ - url: '/token/update', + url: '/erc20/update', method: 'post', data, }); diff --git a/src/services/system/role.ts b/src/services/system/role.ts index 7813827..987ad4d 100644 --- a/src/services/system/role.ts +++ b/src/services/system/role.ts @@ -9,7 +9,7 @@ import request from '@/utils/request'; */ export const getRoleList = (params) => { return request.request({ - url: '/user/role', + url: '/user/role/get', method: 'get', params, }); diff --git a/src/utils/table.ts b/src/utils/table.ts index e19d161..a8bd628 100644 --- a/src/utils/table.ts +++ b/src/utils/table.ts @@ -5,7 +5,7 @@ export const fetchTableData = async ( formatObj: any = {}, ) => { params.page = params.current; - params.page_size = params.pageSize; + params.size = params.pageSize; delete params.current; delete params.pageSize; const res = (await fetch(params)) || {}; diff --git a/src/utils/web3.ts b/src/utils/web3.ts new file mode 100644 index 0000000..c97b085 --- /dev/null +++ b/src/utils/web3.ts @@ -0,0 +1,147 @@ +import Web3 from 'web3'; +import detectEthereumProvider from '@metamask/detect-provider'; +import { message } from 'antd'; +import BigNumber from 'bignumber.js'; + +let provider: any; + +export const web3 = new Web3(); +if (typeof window.ethereum !== 'undefined') { + web3.eth.defaultAccount = window.ethereum.selectedAddress; +} + +export async function initWeb3() { + provider = await detectEthereumProvider(); + + if (!provider) { + console.log('请安装MetaMask'); + return false; + } + + try { + web3.setProvider(provider); + const accounts = await provider.request({ + method: 'eth_requestAccounts', + }); + web3.eth.defaultAccount = accounts[0]; + return true; + } catch (reason) { + switch (reason) { + case 'Already processing eth_requestAccounts. Please wait.': // 已有请求存在 + message.warning('请打开MetaMask完成授权'); + break; + case 'User rejected provider access': //如果用户拒绝了登录请求 + message.warning('请同意登录请求'); + break; + default: + // 本不该执行到这里,但是真到这里了,说明发生了意外 + message.warning('登录出错!err:' + reason); + break; + } + } + return false; +} + +//发布合约 +/** + * + * @param abi 合约ABI + * @param bin 合约二进制 + */ +export async function deployContract(abi: string, bin: string, params) { + const contract = new web3.eth.Contract(eval('(' + abi + ')')); + const result = await contract + .deploy({ + data: '0x' + bin, + arguments: params, + }) + .send({ from: web3.eth.defaultAccount + '', gas: 3000000 }, async function (e, contract) {}); + return result._address; +} + +// 代币转账 +/** + * + * @param abi 合约ABI + * @param address 合约地址 + * @param toAddress 转账地址 + */ +export async function transfer(abi: string, address: string, toAddress: string) { + const contract = new web3.eth.Contract(eval('(' + abi + ')'), address); + await contract.methods + .transfer(toAddress, new BigNumber(1 * Math.pow(10, 18))) + .send({ from: web3.eth.defaultAccount }), + function (error, transactionHash) { + if (!error) { + console.log('transactionHash is ' + transactionHash); + } else { + console.log(error); + } + }; +} + +// NFT创建 +/** + * + * @param abi 合约ABI + * @param address 合约地址 + * @param toAddress 转账地址 + */ + +export async function NFTMint(params: any) { + if (params.toAddress == '' || params.toAddress == null || params.toAddress == undefined) { + params.toAddress = web3.eth.defaultAccount; + } + const contract = new web3.eth.Contract(eval('(' + params.abi + ')'), params.address); + await contract.methods + .Mint(params.toAddress, params.token_id) + .send({ from: web3.eth.defaultAccount }), + function (error, transactionHash) { + if (!error) { + return transactionHash; + } else { + console.log(error); + } + }; +} + +// NFT转移 +/** + * + * @param abi 合约ABI + * @param address 合约地址 + * @param toAddress 转账地址 + * @param token_id + */ +export async function transferNFT(params: any) { + const contract = new web3.eth.Contract(eval('(' + params.abi + ')'), params.address); + await contract.methods + .safeTransferFrom(web3.eth.defaultAccount, params.toAddress, params.token_id) + .send({ from: web3.eth.defaultAccount }), + function (error, transactionHash) { + if (!error) { + return transactionHash; + } else { + console.log(error); + } + }; +} + +// NFT销毁 +/** + * + * @param abi 合约ABI + * @param address 合约地址 + * @param token_id + */ +export async function burnNFT(params: any) { + const contract = new web3.eth.Contract(eval('(' + params.abi + ')'), params.address); + await contract.methods.Burn(params.token_id).send({ from: web3.eth.defaultAccount }), + function (error, transactionHash) { + if (!error) { + return transactionHash; + } else { + console.log(error); + } + }; +}