From 6437428c05dbb1cf5beb447d01afba2dddd374f3 Mon Sep 17 00:00:00 2001 From: john Date: Thu, 27 Jun 2024 17:00:45 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=89=20init:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 8 +- .env.test | 6 +- index.html | 4 +- src/App.css | 4 +- src/App.tsx | 8 +- src/assets/font/DMSans_18pt-Medium.ttf | Bin 56396 -> 0 bytes src/assets/font/SpaceGrotesk-Medium.ttf | Bin 0 -> 86616 bytes src/components/Header.module.css | 4 +- src/components/Header.tsx | 54 +- src/components/RecordsItem.module.css | 2 +- src/components/WalletProvider.tsx | 6 +- src/contract/abi/RedDevils.json | 451 -------------- src/contract/abi/edgeAiNode.json | 237 +++++++ src/contract/utils.ts | 155 +---- src/hook/usePagination.ts | 37 ++ src/i18n/init.ts | 18 +- src/i18n/translation/cn.json | 107 ---- src/i18n/translation/de.json | 107 ---- src/i18n/translation/en.json | 33 +- src/i18n/translation/jp.json | 107 ---- src/i18n/translation/tw.json | 107 ---- src/pages/AirDropRecord.module.css | 9 - src/pages/AirDropRecord.tsx | 97 --- src/pages/AssetRecord.module.css | 9 - src/pages/AssetRecord.tsx | 212 ------- src/pages/Home.module.css | 99 +-- src/pages/Home.tsx | 577 +++++++----------- src/pages/InvitationList.tsx | 54 +- src/pages/LevelUp.module.css | 303 --------- src/pages/LevelUp.tsx | 275 --------- src/pages/Mint.module.css | 103 +++- src/pages/Mint.tsx | 166 +++-- src/server/api.ts | 29 +- src/server/module.d.ts | 66 +- src/style/ant-cover-m.css | 125 +++- .../react-data-table-component-cover-m.css | 4 +- src/utils/index.ts | 33 +- src/utils/wallet.ts | 36 +- vite.config.ts | 4 +- 39 files changed, 1062 insertions(+), 2594 deletions(-) delete mode 100644 src/assets/font/DMSans_18pt-Medium.ttf create mode 100644 src/assets/font/SpaceGrotesk-Medium.ttf delete mode 100644 src/contract/abi/RedDevils.json create mode 100644 src/contract/abi/edgeAiNode.json create mode 100644 src/hook/usePagination.ts delete mode 100644 src/i18n/translation/cn.json delete mode 100644 src/i18n/translation/de.json delete mode 100644 src/i18n/translation/jp.json delete mode 100644 src/i18n/translation/tw.json delete mode 100644 src/pages/AirDropRecord.module.css delete mode 100644 src/pages/AirDropRecord.tsx delete mode 100644 src/pages/AssetRecord.module.css delete mode 100644 src/pages/AssetRecord.tsx delete mode 100644 src/pages/LevelUp.module.css delete mode 100644 src/pages/LevelUp.tsx diff --git a/.env.development b/.env.development index 39143b7..af15357 100644 --- a/.env.development +++ b/.env.development @@ -1,12 +1,12 @@ ### # @LastEditors: John # @Date: 2024-06-18 10:12:21 - # @LastEditTime: 2024-06-25 14:04:33 + # @LastEditTime: 2024-06-27 15:34:18 # @Author: John ### -VITE_BASE_URL=http://192.168.10.167:5173/ +VITE_BASE_URL= VITE_BASE_API_URL=/dev VITE_PARTICIPATE_CHAIN_ID=97 -VITE_PURCHASED_CONTRACT_ADDRESS=0x7aAe4f2CA23482B58D6f9e8d1fBb5e413e7013c8 -VITE_NETWORK_USDT_ADDRESS=0xf9A18B7FC8Eb118f8Ad59fBD6eb1A181eaCb4E63 +VITE_PURCHASED_CONTRACT_ADDRESS=0x3000782e8ba573eFaC3fe72930A963160e752B60 +VITE_NETWORK_USDT_ADDRESS=0x342436983fF95C38878248504Ea26d6724A51054 VITE_CHECK_TRANSACTION_DETAILS_URL=https://testnet.bscscan.com/ \ No newline at end of file diff --git a/.env.test b/.env.test index 1c1e5f6..d680fa5 100644 --- a/.env.test +++ b/.env.test @@ -1,12 +1,12 @@ ### # @LastEditors: John # @Date: 2024-06-24 18:38:45 - # @LastEditTime: 2024-06-25 14:04:37 + # @LastEditTime: 2024-06-27 14:35:41 # @Author: John ### VITE_BASE_URL=http://wwwtest.exgo.pro VITE_BASE_API_URL=http://wwwtest.exgo.pro VITE_PARTICIPATE_CHAIN_ID=97 -VITE_PURCHASED_CONTRACT_ADDRESS=0x7aAe4f2CA23482B58D6f9e8d1fBb5e413e7013c8 -VITE_NETWORK_USDT_ADDRESS=0xf9A18B7FC8Eb118f8Ad59fBD6eb1A181eaCb4E63 +VITE_PURCHASED_CONTRACT_ADDRESS=0x3000782e8ba573eFaC3fe72930A963160e752B60 +VITE_NETWORK_USDT_ADDRESS=0x342436983fF95C38878248504Ea26d6724A51054 VITE_CHECK_TRANSACTION_DETAILS_URL=https://testnet.bscscan.com/ \ No newline at end of file diff --git a/index.html b/index.html index 5a786b0..4689c02 100644 --- a/index.html +++ b/index.html @@ -1,7 +1,7 @@ @@ -13,7 +13,7 @@ name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1, minimum-scale=1, user-scalable=no" /> - red devils + Edge AI Node
diff --git a/src/App.css b/src/App.css index 1b4bf02..da8b319 100644 --- a/src/App.css +++ b/src/App.css @@ -7,8 +7,8 @@ html, } @font-face { - font-family: "DM Sans"; - src: url("./assets/font/DMSans_18pt-Medium.ttf") format("truetype"); + font-family: "Space Grotesk"; + src: url("./assets/font/SpaceGrotesk-Medium.ttf") format("truetype"); } * { diff --git a/src/App.tsx b/src/App.tsx index 74efe28..0e6bc38 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,7 @@ /* * @LastEditors: John * @Date: 2024-06-17 17:20:03 - * @LastEditTime: 2024-06-21 14:19:52 + * @LastEditTime: 2024-06-26 16:00:00 * @Author: John */ import { Route, Routes } from "react-router-dom"; @@ -12,9 +12,6 @@ import Home from "./pages/Home"; import Header from "./components/Header"; import Mint from "./pages/Mint"; import RouterLogProvider from "./context/RouterContext"; -import LevelUp from "./pages/LevelUp"; -import AssetRecord from "./pages/AssetRecord"; -import AirDropRecord from "./pages/AirDropRecord"; import InvitationList from "./pages/InvitationList"; import { useEffect } from "react"; import { useTranslation } from "react-i18next"; @@ -52,9 +49,6 @@ function App() { } /> } /> - } /> - } /> - } /> }> diff --git a/src/assets/font/DMSans_18pt-Medium.ttf b/src/assets/font/DMSans_18pt-Medium.ttf deleted file mode 100644 index 188957b496d2dcdaef0463bde490c9dcd15097b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56396 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 literal 0 HcmV?d00001 diff --git a/src/components/Header.module.css b/src/components/Header.module.css index 516acbb..3449260 100644 --- a/src/components/Header.module.css +++ b/src/components/Header.module.css @@ -22,7 +22,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 16px; font-weight: bold; line-height: normal; @@ -49,7 +49,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: bold; line-height: normal; diff --git a/src/components/Header.tsx b/src/components/Header.tsx index fc89403..4ef53e3 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,7 +1,7 @@ /* * @LastEditors: John * @Date: 2024-06-18 15:16:31 - * @LastEditTime: 2024-06-26 14:49:22 + * @LastEditTime: 2024-06-27 15:29:00 * @Author: John */ import Picker, { @@ -38,15 +38,9 @@ export default function () { const navTitle = useMemo(() => { switch (location.pathname) { case "/mint": - return t("铸造 NFT"); - case "/levelup": - return t("级别提升"); - case "/assetrecord": - return t("收益记录"); - case "/airdroprecord": - return t("RMOB记录"); + return t("Buy Node"); case "/invitationlist": - return t("直推列表"); + return t("Invitation List"); default: return t("返回"); } @@ -57,45 +51,9 @@ export default function () {
- {t("红魔NFT")} - { - switch (node.key) { - case Lang.en: - i18n.changeLanguage(Lang.en); - UpdateLang(Lang.en); - break; - case Lang.cn: - i18n.changeLanguage(Lang.cn); - UpdateLang(Lang.cn); - break; - case Lang.tw: - i18n.changeLanguage(Lang.tw); - UpdateLang(Lang.tw); - break; - case Lang.jp: - i18n.changeLanguage(Lang.jp); - UpdateLang(Lang.jp); - break; - case Lang.de: - i18n.changeLanguage(Lang.de); - UpdateLang(Lang.de); - break; - default: - break; - } - }} - trigger="click" - > - - + + {t("YOTTA Edge AI Node")} +
{location.pathname != "/" && ( diff --git a/src/components/RecordsItem.module.css b/src/components/RecordsItem.module.css index 0d1a3b9..89bc64e 100644 --- a/src/components/RecordsItem.module.css +++ b/src/components/RecordsItem.module.css @@ -11,7 +11,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 12px; font-weight: 500; line-height: normal; diff --git a/src/components/WalletProvider.tsx b/src/components/WalletProvider.tsx index 0d0b8fc..24803bb 100644 --- a/src/components/WalletProvider.tsx +++ b/src/components/WalletProvider.tsx @@ -1,7 +1,7 @@ /* * @LastEditors: John * @Date: 2024-06-17 18:01:43 - * @LastEditTime: 2024-06-24 18:51:52 + * @LastEditTime: 2024-06-27 14:51:11 * @Author: John */ /* @@ -34,7 +34,7 @@ const projectId = "680d2de71bbabc3e79363f1e6b513a68"; // 2. Create wagmiConfig const metadata = { name: "yotta-node", - description: "red devils dapp", + description: "Edge AI Node dapp", url: import.meta.env.BASE_URL, // origin must match your domain & subdomain icons: [`${import.meta.env.BASE_URL}/favicon.svg`], }; @@ -61,7 +61,7 @@ createWeb3Modal({ wagmiConfig: config, projectId, themeVariables: { - "--w3m-accent": "#ea6d28", + "--w3m-accent": "#2dfcfc", }, featuredWalletIds: [ ...(window.ethereum diff --git a/src/contract/abi/RedDevils.json b/src/contract/abi/RedDevils.json deleted file mode 100644 index bc66142..0000000 --- a/src/contract/abi/RedDevils.json +++ /dev/null @@ -1,451 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "hongMoAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "payAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "p1", - "type": "address" - }, - { - "internalType": "address", - "name": "p2", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "buyAddr", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "orderId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "paymentType", - "type": "uint256" - } - ], - "name": "BuySuccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "buyAddr", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "orderId", - "type": "uint256" - } - ], - "name": "RewardSuccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "buyAddr", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "orderId", - "type": "uint256" - } - ], - "name": "UpgradeRange", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "orderId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paymentType", - "type": "uint256" - } - ], - "name": "buyHMNFT", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "orderId", - "type": "uint256" - } - ], - "name": "getOrderStatus", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hongMoNFT", - "outputs": [ - { - "internalType": "contract HongMoNFT", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "payee1", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "payee2", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "price", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paymentTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "orderId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "hashStr", - "type": "bytes32" - } - ], - "name": "reward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "setNFTAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "a", - "type": "address" - }, - { - "internalType": "address", - "name": "b", - "type": "address" - } - ], - "name": "setPayeeAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "p", - "type": "uint256" - } - ], - "name": "setPrice", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "setTokenIndex", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "setUSDCAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "tokenIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "orderId", - "type": "uint256" - } - ], - "name": "upgradePrivilege", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "usdc", - "outputs": [ - { - "internalType": "contract IERC20", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/src/contract/abi/edgeAiNode.json b/src/contract/abi/edgeAiNode.json new file mode 100644 index 0000000..4caacf3 --- /dev/null +++ b/src/contract/abi/edgeAiNode.json @@ -0,0 +1,237 @@ +[ + { + "inputs": [ + { + "internalType": "int256", + "name": "num", + "type": "int256" + } + ], + "name": "AddIllegalTxCount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "orderId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "buyNode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tokenAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "orderId", + "type": "uint256" + } + ], + "name": "BuyNode", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTokenAddress", + "type": "address" + } + ], + "name": "changeTokenAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "CurrentSoldNode", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GetTimpstamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "IllegalTxCount", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_SELL_NODE", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/contract/utils.ts b/src/contract/utils.ts index 54010b0..6ad39f8 100644 --- a/src/contract/utils.ts +++ b/src/contract/utils.ts @@ -1,7 +1,7 @@ /* * @LastEditors: John * @Date: 2024-06-19 15:48:57 - * @LastEditTime: 2024-06-25 15:28:36 + * @LastEditTime: 2024-06-27 11:31:09 * @Author: John */ import { config } from "@/components/WalletProvider"; @@ -15,7 +15,7 @@ import { import { encodeFunctionData } from "viem/utils"; import erc20Abi from "@/contract/abi/erc20abi.json"; import usdtAbi from "@/contract/abi/USDT.json"; -import RedDevilsAbi from "@/contract/abi/RedDevils.json"; +import edgeAiNodeAbi from "@/contract/abi/edgeAiNode.json"; import i18next from "i18next"; import { BaseError } from "wagmi"; @@ -144,17 +144,22 @@ export const authorizedU = async (uNum: bigint) => { * @returns */ export async function payByContract( - amount: bigint, + recipients: string[], + amount: bigint[], orderID: string, - payInduction: number + timestamp: number ) { console.log("pay buy contract params", { amount, orderID }); console.log("NETWORK_USDT:", import.meta.env.VITE_NETWORK_USDT_ADDRESS); return new Promise(async (reslove, reject) => { try { + let totalAmout = 0n; + for (let i = 0; i < amount.length; i++) { + totalAmout += amount[i]; + } const balance = await getBalance(); - if (balance < amount) { + if (balance < totalAmout) { console.log("用户代币余额不足"); reject(new BaseError(i18next.t("余额不足"))); return; @@ -162,27 +167,27 @@ export async function payByContract( console.log("当前要授权的U:", amount); let approvedU = await getApproveUsdt(); - if (approvedU < amount) { - await authorizedU(amount); + if (approvedU < totalAmout) { + await authorizedU(totalAmout); } - console.log("参数:", amount, orderID, payInduction); + console.log("参数:", recipients, amount, orderID, timestamp); estimateGas(config, { to: import.meta.env.VITE_PURCHASED_CONTRACT_ADDRESS, data: encodeFunctionData({ - abi: RedDevilsAbi, - functionName: "buyHMNFT", - args: [amount, orderID, payInduction], + abi: edgeAiNodeAbi, + functionName: "buyNode", + args: [recipients, amount, orderID, timestamp], }), }) .then((gas) => { const gasPrice = (gas * 12n) / 10n; console.log("estimate gas:%d , my gas: %d", gas, gasPrice); writeContract(config, { - abi: RedDevilsAbi, + abi: edgeAiNodeAbi, address: import.meta.env.VITE_PURCHASED_CONTRACT_ADDRESS, - functionName: "buyHMNFT", - args: [amount, orderID, payInduction], + functionName: "buyNode", + args: [recipients, amount, orderID, timestamp], gas: gasPrice, }) .then((receipt) => { @@ -190,12 +195,12 @@ export async function payByContract( reslove(receipt); }) .catch((err: BaseError) => { - console.log("buyHMNFT Transaction err", err); + console.log("buyNode Transaction err", err); reject(err); }); }) .catch((err: BaseError) => { - console.log("buyHMNFT estimateGas err", err); + console.log("buyNode estimateGas err", err); reject(err); }); } catch (err) { @@ -204,121 +209,3 @@ export async function payByContract( } }); } - -/** - * upGradeByContract - * @param amount - * @param orderID - * @returns - */ -export async function upGradeByContract(amount: bigint, orderID: string) { - console.log("pay buy contract params", { amount, orderID }); - console.log("NETWORK_USDT:", import.meta.env.VITE_NETWORK_USDT_ADDRESS); - - return new Promise(async (reslove, reject) => { - try { - const balance = await getBalance(); - if (balance < amount) { - console.log("用户代币余额不足"); - reject(new BaseError(i18next.t("余额不足"))); - return; - } - - console.log("当前要授权的U:", amount); - let approvedU = await getApproveUsdt(); - if (approvedU < amount) { - await authorizedU(amount); - } - - console.log("参数:", amount, orderID); - estimateGas(config, { - to: import.meta.env.VITE_PURCHASED_CONTRACT_ADDRESS, - data: encodeFunctionData({ - abi: RedDevilsAbi, - functionName: "upgradePrivilege", - args: [amount, orderID], - }), - }) - .then((gas) => { - const gasPrice = (gas * 12n) / 10n; - console.log("estimate gas:%d , my gas: %d", gas, gasPrice); - writeContract(config, { - abi: RedDevilsAbi, - address: import.meta.env.VITE_PURCHASED_CONTRACT_ADDRESS, - functionName: "upgradePrivilege", - args: [amount, orderID], - gas: gasPrice, - }) - .then((receipt) => { - console.log("write contract success!, receipt:", receipt); - reslove(receipt); - }) - .catch((err: BaseError) => { - console.log("upgradePrivilege Transaction err", err); - reject(err); - }); - }) - .catch((err: BaseError) => { - console.log("upgradePrivilege estimateGas err", err); - reject(err); - }); - } catch (err) { - reject(new BaseError(`${err}`)); - } - }); -} - -/** - * receiveByContract - * @param amount - * @param orderID - * @returns - */ -export async function receiveByContract( - amount: bigint, - paymentTime: number, - orderID: string, - hashStr: string -) { - console.log("pay buy contract params", { amount, orderID }); - console.log("NETWORK_USDT:", import.meta.env.VITE_NETWORK_USDT_ADDRESS); - - return new Promise(async (reslove, reject) => { - try { - console.log("参数:", amount, paymentTime, orderID, hashStr); - estimateGas(config, { - to: import.meta.env.VITE_PURCHASED_CONTRACT_ADDRESS, - data: encodeFunctionData({ - abi: RedDevilsAbi, - functionName: "reward", - args: [amount, paymentTime, orderID, hashStr], - }), - }) - .then((gas) => { - const gasPrice = (gas * 12n) / 10n; - console.log("estimate gas:%d , my gas: %d", gas, gasPrice); - writeContract(config, { - abi: RedDevilsAbi, - address: import.meta.env.VITE_PURCHASED_CONTRACT_ADDRESS, - functionName: "reward", - args: [amount, paymentTime, orderID, hashStr], - gas: gasPrice, - }) - .then((receipt) => { - console.log("write contract success!, receipt:", receipt); - reslove(receipt); - }) - .catch((err: BaseError) => { - console.log("reward Transaction err", err); - reject(err); - }); - }) - .catch((err: BaseError) => { - console.log("reward estimateGas err", err); - reject(err); - }); - } catch (err) { - reject(new BaseError(`${err}`)); - } - }); -} diff --git a/src/hook/usePagination.ts b/src/hook/usePagination.ts new file mode 100644 index 0000000..37cd9db --- /dev/null +++ b/src/hook/usePagination.ts @@ -0,0 +1,37 @@ +import { useRef, useState } from "react"; + +export default function usePagination({ + service, +}: { + service: ({ + pageNum, + pageSize, + }: { + pageNum: number; + pageSize: number; + }) => Promise; +}) { + const pageNum = useRef(0); + const [hasMore, setHasMore] = useState(true); + const [list, setList] = useState>>([]); + + async function loadMore() { + if (!hasMore) return; + const pageSize = 20; + pageNum.current++; + + const newList = await service({ + pageNum: pageNum.current, + pageSize, + }); + if (newList.length < pageSize) setHasMore(false); + + setList([...list, ...newList]); + } + + return { + hasMore, + list, + loadMore, + }; +} diff --git a/src/i18n/init.ts b/src/i18n/init.ts index d672f56..8fb5ee7 100644 --- a/src/i18n/init.ts +++ b/src/i18n/init.ts @@ -1,16 +1,12 @@ /* * @LastEditors: John * @Date: 2024-06-18 10:30:43 - * @LastEditTime: 2024-06-19 16:55:26 + * @LastEditTime: 2024-06-26 15:36:48 * @Author: John */ import i18next from "i18next"; import { initReactI18next } from "react-i18next"; import en from "./translation/en.json"; -import cn from "./translation/cn.json"; -import tw from "./translation/tw.json"; -import jp from "./translation/jp.json"; -import de from "./translation/de.json"; i18next.use(initReactI18next).init({ compatibilityJSON: "v3", // <--- add this line. lng: "en", // if you're using a language detector, do not define the lng option @@ -19,18 +15,6 @@ i18next.use(initReactI18next).init({ en: { translation: en, }, - cn: { - translation: cn, - }, - tw: { - translation: tw, - }, - jp: { - translation: jp, - }, - de: { - translation: de, - }, }, // if you see an error like: "Argument of type 'DefaultTFuncReturn' is not assignable to parameter of type xyz" // set returnNull to false (and also in the i18next.d.ts options) diff --git a/src/i18n/translation/cn.json b/src/i18n/translation/cn.json deleted file mode 100644 index a6e2f62..0000000 --- a/src/i18n/translation/cn.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "AppName": "红魔", - "红魔NFT": "红魔NFT", - "铸造 NFT": "铸造 NFT", - "级别提升": "级别提升", - "收益记录": "收益记录", - "RMOB记录": "RMOB记录", - "直推列表": "直推列表", - "返回": "返回", - "选择语言": "选择语言", - "确定": "确定", - "取消": "取消", - "普通非活跃": "普通非活跃", - "升级": "升级", - "链接钱包": "链接钱包", - "邀请铸造": "邀请铸造", - "团队社长": "团队社长", - "邀请空投": "邀请空投", - "收益": "收益", - "Min结束后按照规则进行空投。": "Min结束后按照规则进行空投。", - "铸造 NFT 获得代币空投": "铸造 NFT 获得代币空投", - "总收益= 已领取 + 待领取": "总收益= 已领取 + 待领取", - "邀请": "邀请", - "邀请链接": "邀请链接", - "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。": "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。", - "数据披露": "数据披露", - "资金池": "资金池", - "社长席位": "社长席位", - "基金会社长席位": "基金会社长席位", - "待领取": "待领取", - "领取": "领取", - "钱包未链接,无法向您显示 NFT": "钱包未链接,无法向您显示 NFT", - "邀请列表": "邀请列表", - "NFT总量:": "NFT总量:", - "MINT余量:": "MINT余量:", - "当前MINT价格:": "当前MINT价格:", - "价格说明:": "价格说明:", - "{{value1}} USDT起,每增加 {{value2}} 名普通会员,NFT价格上涨 {{value3}},既:前 {{value2}} 名价格为 {{value1}} USDT/枚,value4 名价格为{{value1}}u+{{value1}}u*{{value3}}={{value5}} USDT/枚,以此类推。": "{{value1}} USDT起,每增加{{value2}}名普通会员,NFT价格上涨{{value3}},既:前{{value2}}名价格为{{value1}} USDT/枚,{{value4}}名价格为{{value1}}u+{{value1}}u*{{value3}}={{value5}} USDT/枚,以此类推。", - "授权USDT": "授权USDT", - "当前级别": "当前级别", - "普通活跃": "普通活跃", - "提升级别": "提升级别", - "社长": "社长", - "当前升级价格:": "当前升级价格:", - "升级费用xxx USDT起,其中gas费2USDT,剩余部分50%进入资金池,另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加xxx,既第二位社长升级铸造费用为xxxu+xxx*xxx=xxx USDT,以此类推。": "升级费用{{value1}} USDT起,其中gas费2USDT,剩余部分50%进入资金池,另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加{{value2}},既第二位社长升级铸造费用为{{value1}}u+{{value1}}*{{value2}}={{value3}} USDT,以此类推。", - "升级条件": "升级条件", - "普通会员": "普通会员", - "(限量xxx个)": "(限量 {{value}} 个)", - "1. MINT一枚NFT成为非活跃普通会员": "1. MINT一枚NFT成为非活跃普通会员", - "2. MINT NFT并推荐MINT成为活跃普通会员": "2. MINT NFT并推荐MINT成为活跃普通会员", - "3. 享1%代币空投平分(所有普通会员)": "3. 享1%代币空投平分(所有普通会员)", - "4. 活跃普通会员根据推荐MINT数量额外有空投权益。": "4. 活跃普通会员根据推荐MINT数量额外有空投权益。", - "(限量500个)": "(限量500个)", - "1. 先成为活跃普通会员,并推荐MINT 20枚NFT": "1. 先成为活跃普通会员,并推荐MINT 20枚NFT", - "2. 需支付100USDT起升级费用成为社长(第二个起递增10%)": "2. 需支付100USDT起升级费用成为社长(第二个起递增10%)", - "3. 享普通会员权益+0.5%空投代币平分(所有社长)": "3. 享普通会员权益+0.5%空投代币平分(所有社长)", - "4. 享社长升级费用50%平分(扣除2USDT GAS费后)": "4. 享社长升级费用50%平分(扣除2USDT GAS费后)", - "5. 从推荐MINT 21枚开始直推的铸造费用归社长所有": "5. 从推荐MINT 21枚开始直推的铸造费用归社长所有", - "基金会社长": "基金会社长", - "(限量20个)": "(限量20个)", - "1. 先成为社长,并团队中有20个社长": "1. 先成为社长,并团队中有20个社长", - "2. 享社长权益+0.5%空投代币平分(所有基金会社长)": "2. 享社长权益+0.5%空投代币平分(所有基金会社长)", - "3. 另外基金会社长参与所有项目分成": "3. 另外基金会社长参与所有项目分成", - "发放记录": "发放记录", - "升级费平分": "升级费平分", - "直推>20NFT": "直推>20NFT", - "空投记录": "空投记录", - "所有": "所有", - "NFT空投": "NFT空投", - "社长空投": "社长空投", - "直推空投": "直推空投", - "奖励类型": "奖励类型", - "NFT控投": "NFT控投", - "发放时间": "发放时间", - "发放数量": "发放数量", - "领取记录": "领取记录", - "领取时间": "领取时间", - "领取数量": "领取数量", - "领取状态": "领取状态", - "确认中": "确认中", - "领取成功": "领取成功", - "交易取消": "交易取消", - "地址": "地址", - "级别": "级别", - "直推NFT": "直推NFT", - "非活跃普通": "非活跃普通", - "活跃普通": "活跃普通", - - "复制成功": "复制成功", - "领取成功,前往钱包查看": "领取成功,前往钱包查看", - "链接钱包中...": "链接钱包中...", - "无": "无", - "服务器错误": "服务器错误", - "余额不足": "余额不足", - "MINT成功,返回首页查看": "MINT成功,返回首页查看", - "正在授权USDT": "正在授权USDT", - "购买中": "购买中", - "领取中": "领取中", - "MINT Nft 获取邀请链接": "MINT Nft 获取邀请链接", - "链接钱包获取邀请链接": "链接钱包获取邀请链接", - "正在获取已授权金额": "正在获取已授权金额", - "升级成功,返回首页查看": "升级成功,返回首页查看", - "无级别提升": "无级别提升", - "没有更多数据了": "没有更多数据了", - "升级中": "升级中", - "无等级": "无等级" -} diff --git a/src/i18n/translation/de.json b/src/i18n/translation/de.json deleted file mode 100644 index 6b59716..0000000 --- a/src/i18n/translation/de.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "AppName": "Der Rote Teufel", - "红魔NFT": "Der Rote Teufel NFT", - "铸造 NFT": "NFT Prägen", - "级别提升": "Stufenaufstieg", - "收益记录": "Ergebnisrekord", - "RMOB记录": "RMOB Aufzeichnung", - "直推列表": "Direktempfehlungsliste", - "返回": "Zurück", - "选择语言": "Sprache wählen", - "确定": "Bestätigen", - "取消": "Abbrechen", - "普通非活跃": "Inaktiv Mitglied", - "升级": "Upgrade", - "链接钱包": "Wallet verbinden", - "邀请铸造": "Prägen einladen", - "团队社长": "Teamleiter", - "邀请空投": "Airdrop einladen", - "收益": "Einkommen", - "Min结束后按照规则进行空投。": "Airdrop nach dem Ende des Min gemäß den Regeln.", - "铸造 NFT 获得代币空投": "Token-Airdrop durch NFT-Prägung erhalten", - "总收益= 已领取 + 待领取": "Gesamtumsatz = Empfang + Abzuholen", - "邀请": "Einladen", - "邀请链接": "Einladungslink", - "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。": "Normale Mitglieder erhalten für jede Einladung zur Prägung eines NFTs einen Airdrop-Bonus; 20 empfohlene Prägungen führen zum Aufstieg zum Vorsitzenden; 20 Vorsitzende im Team ermöglichen den Aufstieg zum Fundmanager; je mehr Einladungen, desto höher das Level und die Belohnungen.", - "数据披露": "Datenoffenlegung", - "资金池": "Liquiditätspool", - "社长席位": "Vorsitzenderplatz", - "基金会社长席位": "Fundmanagerplatz", - "待领取": "Ausstehend", - "领取": "Erhalten", - "钱包未链接,无法向您显示 NFT": "Wallet nicht verbunden, kann NFT nicht anzeigen", - "邀请列表": "Einladungsliste", - "NFT总量:": "Gesamtzahl der NFTs:", - "MINT余量:": "Verbleibende MINT:", - "当前MINT价格:": "Aktueller MINT-Preis:", - "价格说明:": "Preiserklärung:", - "{{value1}} USDT起,每增加 {{value2}} 名普通会员,NFT价格上涨 {{value3}},既:前 {{value2}} 名价格为 {{value1}} USDT/枚,value4 名价格为{{value1}}u+{{value1}}u*{{value3}}={{value5}} USDT/枚,以此类推。": "Beginnend bei {{value1}} USDT steigt der NFT-Preis um {{value3}} für jede zusätzlichen {{value2}} Mitglieder: die ersten {{value2}} kosten {{value1}} USDT pro Stück, {{value4}} kosten {{value1}}u+{{value1}}u*{{value3}}={{value5}} USDT pro Stück usw.", - "授权USDT": "USDT autorisieren", - "当前级别": "Aktuelles Level", - "普通活跃": "Aktives Mitglied", - "提升级别": "Levelaufstieg", - "社长": "Vorsitzender", - "当前升级价格:": "Aktueller Upgrade-Preis:", - "升级费用xxx USDT起,其中gas费2USDT,剩余部分50%进入资金池,另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加xxx,既第二位社长升级铸造费用为xxxu+xxx*xxx=xxx USDT,以此类推。": "Upgrade-Kosten ab {{value1}} USDT, davon 2USDT Gas-Gebühren, 50% des Restbetrags gehen in den Liquiditätspool und die anderen 50% werden auf alle erfolgreichen Vorsitzenden und Fundmanager aufgeteilt. Ab dem zweiten Vorsitzenden steigen die Prägekosten um {{value2}} pro Aufstieg, also {{value1}}u+{{value1}}*{{value2}}={{value3}} USDT für den zweiten, usw.", - "升级条件": "Upgrade-Bedingungen", - "普通会员": "Normales Mitglied", - "(限量xxx个)": "(Begrenzt auf {{value}} Stück)", - "1. MINT一枚NFT成为非活跃普通会员": "1. Präge ein NFT, um inaktives Mitglied zu werden", - "2. MINT NFT并推荐MINT成为活跃普通会员": "2. Präge und empfehle NFTs, um aktives Mitglied zu werden", - "3. 享1%代币空投平分(所有普通会员)": "3. Erhalte 1% Token-Airdrop gleichmäßig verteilt (alle normalen Mitglieder)", - "4. 活跃普通会员根据推荐MINT数量额外有空投权益。": "4. Aktive Mitglieder erhalten zusätzliche Airdrop-Rechte basierend auf der Anzahl der empfohlenen Prägungen.", - "(限量500个)": "(Begrenzt auf 500 Stück)", - "1. 先成为活跃普通会员,并推荐MINT 20枚NFT": "1. Werde zuerst aktives Mitglied und empfehle die Prägung von 20 NFTs", - "2. 需支付100USDT起升级费用成为社长(第二个起递增10%)": "2. Zahle ab 100USDT für das Upgrade zum Vorsitzenden (ab dem zweiten um 10% steigend)", - "3. 享普通会员权益+0.5%空投代币平分(所有社长)": "3. Erhalte die Rechte eines normalen Mitglieds + 0,5% Token-Airdrop gleichmäßig verteilt (alle Vorsitzenden)", - "4. 享社长升级费用50%平分(扣除2USDT GAS费后)": "4. Erhalte 50% der Upgrade-Kosten des Vorsitzenden gleichmäßig verteilt (abzüglich 2USDT Gas-Gebühr)", - "5. 从推荐MINT 21枚开始直推的铸造费用归社长所有": "5. Ab 21 empfohlenen Prägungen gehen die Prägekosten direkt an den Vorsitzenden", - "基金会社长": "Fundmanager", - "(限量20个)": "(Begrenzt auf 20 Stück)", - "1. 先成为社长,并团队中有20个社长": "1. Werde zuerst Vorsitzender und habe 20 Vorsitzende im Team", - "2. 享社长权益+0.5%空投代币平分(所有基金会社长)": "2. Erhalte die Rechte eines Vorsitzenden + 0,5% Token-Airdrop gleichmäßig verteilt (alle Fundmanager)", - "3. 另外基金会社长参与所有项目分成": "3. Fundmanager nehmen zusätzlich an allen Projektgewinnen teil", - "发放记录": "Verteilungsprotokoll", - "升级费平分": "Upgrade-Gebührenverteilung", - "直推>20NFT": "Direktempfehlung > 20 NFT", - "空投记录": "Airdrop-Protokoll", - "所有": "Alle", - "NFT空投": "NFT-Airdrop", - "社长空投": "Vorsitzender-Airdrop", - "直推空投": "Direktempfehlung Airdrop", - "奖励类型": "Belohnungstyp", - "NFT控投": "NFT-Besitz", - "发放时间": "Verteilungszeit", - "发放数量": "Verteilungsmenge", - "领取记录": "Empfangsprotokoll", - "领取时间": "Empfangszeit", - "领取数量": "Empfangsmenge", - "领取状态": "Empfangsstatus", - "确认中": "Bestätigung läuft", - "领取成功": "Erfolgreich empfangen", - "交易取消": "Transaktion abgebrochen", - "地址": "Adresse", - "级别": "Stufe", - "直推NFT": "Direktempfehlung NFT", - "非活跃普通": "Inaktiv allgemein", - "活跃普通": "Aktiv allgemein", - - "复制成功": "Erfolgreich kopiert", - "领取成功,前往钱包查看": "Erfolgreich abgerufen. Bitte überprüfen Sie Ihre Brieftasche.", - "链接钱包中...": "Wallet wird verbunden...", - "无": "Keiner", - "服务器错误": "Serverfehler", - "余额不足": "Unzureichendes Guthaben", - "MINT成功,返回首页查看": "MINT erfolgreich, zur Startseite zurückkehren, um nachzusehen.", - "正在授权USDT": "USDT wird autorisiert", - "购买中": "In Bearbeitung", - "领取中": "In Bearbeitung", - "MINT Nft 获取邀请链接": "MINT Nft Einladungslink erhalten", - "链接钱包获取邀请链接": "Verknüpfen Sie Ihre Brieftasche, um den Einladungslink zu erhalten.", - "正在获取已授权金额": "Aktuell wird der autorisierte Betrag abgerufen.", - "升级成功,返回首页查看": "Upgrade erfolgreich abgeschlossen, zurück zur Startseite zur Ansicht.", - "无级别提升": "Beförderung ohne Rang", - "没有更多数据了": "Keine weiteren Daten", - "升级中": "Wird aktualisiert", - "无等级": "Keine Bewertung" -} diff --git a/src/i18n/translation/en.json b/src/i18n/translation/en.json index dab5061..6e3e2f2 100644 --- a/src/i18n/translation/en.json +++ b/src/i18n/translation/en.json @@ -1,11 +1,11 @@ { - "AppName": "Red Devils", - "红魔NFT": "Red Devils NFT", - "铸造 NFT": "Mint NFT", + "AppName": "Edge AI Node", + "YOTTA Edge AI Node": "YOTTA Edge AI Node", + "Buy Node": "Buy Node", "级别提升": "Level Up", "收益记录": "Revenue Record", "RMOB记录": "RMOB Records", - "直推列表": "Direct Referral List", + "Invitation List": "Invitation List", "返回": "Back", "选择语言": "Select Language", "确定": "Confirm", @@ -13,23 +13,23 @@ "普通非活跃": "Inactive Member", "升级": "Upgrade", "链接钱包": "Connect Wallet", - "邀请铸造": "Invite to Mint", - "团队社长": "Team Leader", - "邀请空投": "Invite Airdrop", + "Direct Node": "Direct Node", + "Team Node": "Team Node", + "Push income": "Push income", "收益": "Income", - "Min结束后按照规则进行空投。": "Airdrop will follow the rules after Min ends.", - "铸造 NFT 获得代币空投": "Mint NFT for Token Airdrop", + "Start mining after node subscription ends.": "Start mining after node subscription ends.", + "Buy Edge AI Node.": "Buy Edge AI Node.", "总收益= 已领取 + 待领取": "Total Revenue = Claimed + Pending", "邀请": "Invite", "邀请链接": "Invite Link", - "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。": "Regular members get an airdrop for each NFT minted through their invite; recommending 20 NFTs upgrades to Leader; having 20 Leaders in the team upgrades to Foundation Leader; more invites lead to higher levels and more benefits.", + "Invite your friends to become YOTTA nodes and you will get a 20% rebate.": "Invite your friends to become YOTTA nodes and you will get a 20% rebate.", "数据披露": "Data Disclosure", "资金池": "Fund Pool", "社长席位": "Leader Seats", "基金会社长席位": "Foundation Leader Seats", "待领取": "Pending", "领取": "Claim", - "钱包未链接,无法向您显示 NFT": "Wallet not linked, unable to display NFT", + "The wallet is not linked and cannot show you the Node.": "The wallet is not linked and cannot show you the Node.", "邀请列表": "Invite List", "NFT总量:": "Total NFTs:", "MINT余量:": "Remaining MINT:", @@ -92,16 +92,17 @@ "无": "None", "服务器错误": "Server Error", "余额不足": "Insufficient balance", - "MINT成功,返回首页查看": "MINT succeeded, return to the homepage to check.", - "正在授权USDT": "Authorizing USDT", + "Buy successful. Please return to the homepage to view.": "Buy successful. Please return to the homepage to view.", + "正在授权USDT": "Approving USDT", "购买中": "Purchasing", "领取中": "Processing", - "MINT Nft 获取邀请链接": "Mint NFT to get invitation link", - "链接钱包获取邀请链接": "Link your wallet to get the invitation link.", + "Buy Edge AI Node to get invitation link": "Buy Edge AI Node to get invitation link", + "Link wallet to get invitation link": "Link wallet to get invitation link", "正在获取已授权金额": "Currently retrieving authorized amount.", "升级成功,返回首页查看": "Upgrade successful, return to homepage to view.", "无级别提升": "Promotion without rank", "没有更多数据了": "No more data", "升级中": "Upgrading", - "无等级": "No Grade" + "无等级": "No Grade", + "invalid invitation link": "invalid invitation link" } diff --git a/src/i18n/translation/jp.json b/src/i18n/translation/jp.json deleted file mode 100644 index 3cb88d7..0000000 --- a/src/i18n/translation/jp.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "AppName": "紅魔", - "红魔NFT": "紅魔NFT", - "铸造 NFT": "NFT 鋳造", - "级别提升": "レベルアップ", - "收益记录": "収益実績", - "RMOB记录": "RMOB記録", - "直推列表": "ダイレクト推薦リスト", - "返回": "戻る", - "选择语言": "言語選択", - "确定": "確定", - "取消": "キャンセル", - "普通非活跃": "非活躍メンバー", - "升级": "アップグレード", - "链接钱包": "ウォレットを接続", - "邀请铸造": "鋳造を招待", - "团队社长": "チームリーダー", - "邀请空投": "エアドロップ招待", - "收益": "所得", - "Min结束后按照规则进行空投。": "Min終了後、ルールに従ってエアドロップを行います。", - "铸造 NFT 获得代币空投": "NFTを鋳造してトークンエアドロップを獲得", - "总收益= 已领取 + 待领取": "総収入 = 受領済み + 回収対象", - "邀请": "招待", - "邀请链接": "招待リンク", - "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。": "一般会員はNFT鋳造の招待ごとにエアドロップを獲得;20個のNFTを鋳造することでリーダーに昇格;チーム内に20人のリーダーがいるとファンドリーダーに昇格;招待が多いほどレベルが上がり、特典が増える。", - "数据披露": "データ開示", - "资金池": "資金プール", - "社长席位": "リーダー席", - "基金会社长席位": "ファンドリーダー席", - "待领取": "未受領", - "领取": "受領", - "钱包未链接,无法向您显示 NFT": "ウォレットが接続されていないため、NFTを表示できません", - "邀请列表": "招待リスト", - "NFT总量:": "NFT総量:", - "MINT余量:": "残りのMINT:", - "当前MINT价格:": "現在のMINT価格:", - "价格说明:": "価格説明:", - "{{value1}} USDT起,每增加 {{value2}} 名普通会员,NFT价格上涨 {{value3}},既:前 {{value2}} 名价格为 {{value1}} USDT/枚,value4 名价格为{{value1}}u+{{value1}}u*{{value3}}={{value5}} USDT/枚,以此类推。": "{{value1}} USDTから、{{value2}}人の会員が増えるごとにNFT価格が{{value3}}上昇:最初の{{value2}}人は{{value1}}USDT/個、{{value4}}人は{{value1}}u+{{value1}}u*{{value3}}={{value5}} USDT/個、以降も同様。", - "授权USDT": "USDTの承認", - "当前级别": "現在のレベル", - "普通活跃": "活躍メンバー", - "提升级别": "レベルアップ", - "社长": "リーダー", - "当前升级价格:": "現在のアップグレード価格:", - "升级费用xxx USDT起,其中gas费2USDT,剩余部分50%进入资金池,另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加xxx,既第二位社长升级铸造费用为xxxu+xxx*xxx=xxx USDT,以此类推。": "アップグレード費用は{{value1}} USDTから、うちガス代2USDT、残りの50%は資金プールに入り、もう50%はアップグレードに成功したリーダーとファンドリーダーに分配。2人目のリーダーからは、アップグレード費用が{{value2}}ずつ増加、つまり2人目は{{value1}}u+{{value1}}*{{value2}}={{value3}} USDT、以降も同様。", - "升级条件": "アップグレード条件", - "普通会员": "一般会員", - "(限量xxx个)": "(限定 {{value}} 個)", - "1. MINT一枚NFT成为非活跃普通会员": "1. NFTを1枚鋳造して非活躍メンバーになる", - "2. MINT NFT并推荐MINT成为活跃普通会员": "2. NFTを鋳造し、他者に鋳造を推奨して活躍メンバーになる", - "3. 享1%代币空投平分(所有普通会员)": "3. 一般会員は1%のトークンエアドロップを均等に分配", - "4. 活跃普通会员根据推荐MINT数量额外有空投权益。": "4. 活躍メンバーは推奨MINT数に応じて追加エアドロップ権を持つ。", - "(限量500个)": "(限定500個)", - "1. 先成为活跃普通会员,并推荐MINT 20枚NFT": "1. まず活躍メンバーになり、20枚のNFTを推奨して鋳造", - "2. 需支付100USDT起升级费用成为社长(第二个起递增10%)": "2. 100USDTからアップグレード費用を支払いリーダーになる(2人目以降は10%増加)", - "3. 享普通会员权益+0.5%空投代币平分(所有社长)": "3. 一般会員の権利に加え、リーダーは0.5%のトークンエアドロップを均等に分配", - "4. 享社长升级费用50%平分(扣除2USDT GAS费后)": "4. リーダーのアップグレード費用の50%を分配(2USDTのガス代を除く)", - "5. 从推荐MINT 21枚开始直推的铸造费用归社长所有": "5. 推奨MINTが21枚以上になると、鋳造費用はリーダーのものとなる", - "基金会社长": "ファンドリーダー", - "(限量20个)": "(限定20個)", - "1. 先成为社长,并团队中有20个社长": "1. まずリーダーになり、チームに20人のリーダーがいる", - "2. 享社长权益+0.5%空投代币平分(所有基金会社长)": "2. リーダーの権利に加え、ファンドリーダーは0.5%のトークンエアドロップを均等に分配", - "3. 另外基金会社长参与所有项目分成": "3. さらにファンドリーダーはすべてのプロジェクトの利益分配に参加", - "发放记录": "配布記録", - "升级费平分": "アップグレード費用分配", - "直推>20NFT": "ダイレクト推薦>20NFT", - "空投记录": "エアドロップ記録", - "所有": "すべて", - "NFT空投": "NFTエアドロップ", - "社长空投": "リーダーエアドロップ", - "直推空投": "ダイレクト推薦エアドロップ", - "奖励类型": "報酬タイプ", - "NFT控投": "NFT保有", - "发放时间": "配布時間", - "发放数量": "配布数量", - "领取记录": "受領記録", - "领取时间": "受領時間", - "领取数量": "受領数量", - "领取状态": "受領状態", - "确认中": "確認中", - "领取成功": "受領成功", - "交易取消": "取引キャンセル", - "地址": "アドレス", - "级别": "レベル", - "直推NFT": "ダイレクト推薦NFT", - "非活跃普通": "非活躍一般", - "活跃普通": "活躍一般", - - "复制成功": "コピーが成功しました", - "领取成功,前往钱包查看": "受け取りが成功しました。ウォレットで確認してください。", - "链接钱包中...": "ウォレットをリンク中...", - "无": "無", - "服务器错误": "サーバーエラー", - "余额不足": "ざんだかふそく", - "MINT成功,返回首页查看": "MINTが成功しました。ホームページに戻って確認してください", - "正在授权USDT": "USDTの認証中", - "购买中": "購入中 (こうにゅうちゅう)", - "领取中": "しょりちゅう", - "MINT Nft 获取邀请链接": "MINT Nft 招待リンクを取得する", - "链接钱包获取邀请链接": "ウォレットをリンクして招待リンクを取得します。", - "正在获取已授权金额": "承認済み金額を取得中です", - "升级成功,返回首页查看": "アップグレードが成功しました。ホームページに戻って確認してください。", - "无级别提升": "階級なしの昇進", - "没有更多数据了": "これ以上のデータはありません", - "升级中": "アップグレード中", - "无等级": "グレードなし" -} diff --git a/src/i18n/translation/tw.json b/src/i18n/translation/tw.json deleted file mode 100644 index c52a940..0000000 --- a/src/i18n/translation/tw.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "AppName": "紅魔", - "红魔NFT": "紅魔NFT", - "铸造 NFT": "鑄造 NFT", - "级别提升": "級別提升", - "收益记录": "收益記錄", - "RMOB记录": "RMOB記錄", - "直推列表": "直推列表", - "返回": "返回", - "选择语言": "選擇語言", - "确定": "確定", - "取消": "取消", - "普通非活跃": "普通非活躍", - "升级": "升級", - "链接钱包": "鏈接錢包", - "邀请铸造": "邀請鑄造", - "团队社长": "團隊社長", - "邀请空投": "邀請空投", - "收益": "收益", - "Min结束后按照规则进行空投。": "Min結束後按照規則進行空投。", - "铸造 NFT 获得代币空投": "鑄造 NFT 獲得代幣空投", - "总收益= 已领取 + 待领取": "總收益 = 已領取 + 待領取", - "邀请": "邀請", - "邀请链接": "邀請鏈接", - "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。": "普通會員每邀請鑄造一個NFT可獲得一份空投福利;推薦鑄造20個NFT的可升級為會長;團隊中擁有20位會長可升級為基金會社長;邀請越多級別越高福利越多。", - "数据披露": "數據披露", - "资金池": "資金池", - "社长席位": "社長席位", - "基金会社长席位": "基金會社長席位", - "待领取": "待領取", - "领取": "領取", - "钱包未链接,无法向您显示 NFT": "錢包未鏈接,無法向您顯示 NFT", - "邀请列表": "邀請列表", - "NFT总量:": "NFT總量:", - "MINT余量:": "MINT餘量:", - "当前MINT价格:": "當前MINT價格:", - "价格说明:": "價格說明:", - "{{value1}} USDT起,每增加 {{value2}} 名普通会员,NFT价格上涨 {{value3}},既:前 {{value2}} 名价格为 {{value1}} USDT/枚,value4 名价格为{{value1}}u+{{value1}}u*{{value3}}={{value5}} USDT/枚,以此类推。": "{{value1}} USDT起,每增加{{value2}}名普通會員,NFT價格上漲{{value3}},即:前{{value2}}名價格為{{value1}} USDT/枚,{{value4}}名價格為{{value1}}u+{{value1}}u*{{value3}}={{value5}} USDT/枚,以此類推。", - "授权USDT": "授權USDT", - "当前级别": "當前級別", - "普通活跃": "普通活躍", - "提升级别": "提升級別", - "社长": "社長", - "当前升级价格:": "當前升級價格:", - "升级费用xxx USDT起,其中gas费2USDT,剩余部分50%进入资金池,另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加xxx,既第二位社长升级铸造费用为xxxu+xxx*xxx=xxx USDT,以此类推。": "升級費用{{value1}} USDT起,其中gas費2USDT,剩餘部分50%進入資金池,另外50%平均分給所有升級成功的社長和基金會社長。自第二個社長升級開始,每升級一名社長所需鑄造費用增加{{value2}},即第二位社長升級鑄造費用為{{value1}}u+{{value1}}*{{value2}}={{value3}} USDT,以此類推。", - "升级条件": "升級條件", - "普通会员": "普通會員", - "(限量xxx个)": "(限量 {{value}} 個)", - "1. MINT一枚NFT成为非活跃普通会员": "1. MINT一枚NFT成為非活躍普通會員", - "2. MINT NFT并推荐MINT成为活跃普通会员": "2. MINT NFT並推薦MINT成為活躍普通會員", - "3. 享1%代币空投平分(所有普通会员)": "3. 享1%代幣空投平分(所有普通會員)", - "4. 活跃普通会员根据推荐MINT数量额外有空投权益。": "4. 活躍普通會員根據推薦MINT數量額外有空投權益。", - "(限量500个)": "(限量500個)", - "1. 先成为活跃普通会员,并推荐MINT 20枚NFT": "1. 先成為活躍普通會員,並推薦MINT 20枚NFT", - "2. 需支付100USDT起升级费用成为社长(第二个起递增10%)": "2. 需支付100USDT起升級費用成為社長(第二個起遞增10%)", - "3. 享普通会员权益+0.5%空投代币平分(所有社长)": "3. 享普通會員權益+0.5%空投代幣平分(所有社長)", - "4. 享社长升级费用50%平分(扣除2USDT GAS费后)": "4. 享社長升級費用50%平分(扣除2USDT GAS費後)", - "5. 从推荐MINT 21枚开始直推的铸造费用归社长所有": "5. 從推薦MINT 21枚開始直推的鑄造費用歸社長所有", - "基金会社长": "基金會社長", - "(限量20个)": "(限量20個)", - "1. 先成为社长,并团队中有20个社长": "1. 先成為社長,並團隊中有20個社長", - "2. 享社长权益+0.5%空投代币平分(所有基金会社长)": "2. 享社長權益+0.5%空投代幣平分(所有基金會社長)", - "3. 另外基金会社长参与所有项目分成": "3. 另外基金會社長參與所有項目分成", - "发放记录": "發放記錄", - "升级费平分": "升級費平分", - "直推>20NFT": "直推>20NFT", - "空投记录": "空投記錄", - "所有": "所有", - "NFT空投": "NFT空投", - "社长空投": "社長空投", - "直推空投": "直推空投", - "奖励类型": "獎勵類型", - "NFT控投": "NFT控投", - "发放时间": "發放時間", - "发放数量": "發放數量", - "领取记录": "領取記錄", - "领取时间": "領取時間", - "领取数量": "領取數量", - "领取状态": "領取狀態", - "确认中": "確認中", - "领取成功": "領取成功", - "交易取消": "交易取消", - "地址": "地址", - "级别": "級別", - "直推NFT": "直推NFT", - "非活跃普通": "非活躍普通", - "活跃普通": "活躍普通", - - "复制成功": "複製成功", - "领取成功,前往钱包查看": "領取成功,前往錢包查看", - "链接钱包中...": "連結錢包中...", - "无": "無", - "服务器错误": "伺服器錯誤", - "余额不足": "餘額不足", - "MINT成功,返回首页查看": "MINT成功,返回首頁查看", - "正在授权USDT": "正在授權USDT", - "购买中": "購買中", - "领取中": "處理中", - "MINT Nft 获取邀请链接": "MINT Nft 獲取邀請鏈接", - "链接钱包获取邀请链接": "連結錢包以獲取邀請鏈接。", - "正在获取已授权金额": "正在取得已授權金額", - "升级成功,返回首页查看": "升級成功,返回首頁查看。", - "无级别提升": "無級別提升", - "没有更多数据了": "沒有更多數據了", - "升级中": "升級中", - "无等级": "無等級" -} diff --git a/src/pages/AirDropRecord.module.css b/src/pages/AirDropRecord.module.css deleted file mode 100644 index 90c37ec..0000000 --- a/src/pages/AirDropRecord.module.css +++ /dev/null @@ -1,9 +0,0 @@ -.AirDropRecord { - .recordsList { - display: flex; - flex-direction: column; - gap: 10px; - padding: 0 15px; - margin-top: 20px; - } -} diff --git a/src/pages/AirDropRecord.tsx b/src/pages/AirDropRecord.tsx deleted file mode 100644 index 2b70816..0000000 --- a/src/pages/AirDropRecord.tsx +++ /dev/null @@ -1,97 +0,0 @@ -/* - * @LastEditors: John - * @Date: 2024-06-19 10:43:03 - * @LastEditTime: 2024-06-19 14:25:41 - * @Author: John - */ -import RecordsItem from "@/components/RecordsItem"; -import CapsuleTabs from "antd-mobile/es/components/capsule-tabs"; -import Tabs from "antd-mobile/es/components/tabs"; -import classes from "./AirDropRecord.module.css"; -import { useTranslation } from "react-i18next"; -export default function () { - const { t } = useTranslation(); - return ( - <> - - - - - - - - - -
    - {Array.from({ length: 20 }).map((v, i) => ( -
  • - -
  • - ))} -
-
- -
    -
  • - -
  • -
  • - -
  • -
  • - -
  • -
-
-
- - ); -} diff --git a/src/pages/AssetRecord.module.css b/src/pages/AssetRecord.module.css deleted file mode 100644 index 35ca5c2..0000000 --- a/src/pages/AssetRecord.module.css +++ /dev/null @@ -1,9 +0,0 @@ -.AssetRecord { - .recordsList { - display: flex; - flex-direction: column; - gap: 10px; - padding: 0 15px; - margin-top: 20px; - } -} diff --git a/src/pages/AssetRecord.tsx b/src/pages/AssetRecord.tsx deleted file mode 100644 index 86ae499..0000000 --- a/src/pages/AssetRecord.tsx +++ /dev/null @@ -1,212 +0,0 @@ -/* - * @LastEditors: John - * @Date: 2024-06-18 17:57:13 - * @LastEditTime: 2024-06-25 16:17:20 - * @Author: John - */ -import Tabs from "antd-mobile/es/components/tabs"; -import classes from "./AssetRecord.module.css"; -import { cn, getUrlQueryParam } from "@/utils"; -import CapsuleTabs from "antd-mobile/es/components/capsule-tabs"; -import RecordsItem from "@/components/RecordsItem"; -import { useTranslation } from "react-i18next"; -import { useEffect, useMemo, useRef, useState } from "react"; -import { api_pagling_query_income_record } from "@/server/api"; -import { IncomeRecord, IncomeRecordType } from "@/server/module"; -import { Empty, InfiniteScroll } from "antd-mobile"; -import { CoinName } from "@/constants"; - -export default function () { - const { t } = useTranslation(); - const coinId = useMemo(() => getUrlQueryParam("id"), []); - const coinName = useMemo(() => getUrlQueryParam("name"), []); - const currentType = useRef<1 | 2>(2); - const [issueRecords, setIssueRecords] = useState([]); - const [receiveRecord, setReceiveRecord] = useState( - [] - ); - const conditions = useRef(); - - const pageNum = useRef(0); - const hasMore = useRef(true); - useEffect(() => { - return () => {}; - }, []); - - async function getRecord() { - return new Promise(async (reslove) => { - if (!coinId) return; - - if (!hasMore.current) return; - - const pageSize = 20; - pageNum.current++; - const { data } = await api_pagling_query_income_record().send({ - queryParams: { - id: coinId, - type: currentType.current, - pageNum: pageNum.current, - pageSize, - ...(conditions.current && currentType.current == 2 - ? { status: conditions.current } - : {}), - }, - }); - - if (!data?.data.records) return; - - if (data.data.records.length < pageSize) hasMore.current = false; - - if (currentType.current == 2) { - setIssueRecords([...issueRecords, ...data?.data.records]); - } else { - setReceiveRecord([...receiveRecord, ...data?.data.records]); - } - reslove(); - }); - } - - function resetPaging() { - if (currentType.current == 2) { - setIssueRecords([]); - } else if (currentType.current == 1) { - setReceiveRecord([]); - } - pageNum.current = 0; - hasMore.current = true; - } - - return ( - <> - { - if (parseInt(key) == 1) { - currentType.current = 2; - resetPaging(); - } else { - currentType.current = 1; - resetPaging(); - } - }} - > - - {coinName == CoinName.USDT && ( - { - switch (key) { - case "1": - conditions.current = undefined; - break; - case "2": - conditions.current = 5; - break; - case "3": - conditions.current = 4; - break; - - default: - break; - } - resetPaging(); - }} - > - - - 20NFT")} key="3" /> - - )} - - {coinName == CoinName.RMOB && ( - { - switch (key) { - case "1": - conditions.current = undefined; - break; - case "2": - conditions.current = 6; - break; - case "3": - conditions.current = 7; - break; - case "4": - conditions.current = 8; - break; - case "5": - conditions.current = 9; - break; - default: - break; - } - resetPaging(); - }} - > - - - - - - - )} -
    - {issueRecords?.map((v, i) => ( -
  • - -
  • - ))} - {issueRecords?.length == 0 && } - - {t("没有更多数据了")} - -
-
- -
    - {receiveRecord?.map((v, i) => ( -
  • - -
  • - ))} - {receiveRecord?.length == 0 && } - - {t("没有更多数据了")} - -
-
-
- - ); -} diff --git a/src/pages/Home.module.css b/src/pages/Home.module.css index 1d9dc48..5af7f77 100644 --- a/src/pages/Home.module.css +++ b/src/pages/Home.module.css @@ -16,8 +16,8 @@ background: #171719; - box-shadow: 0px 4px 10px 0px rgba(138, 29, 19, 0.3), - inset 0px 0px 8px 0px #8a1d13; + box-shadow: 0px 4px 10px 0px rgba(45, 252, 252, 0.3), + inset 0px 0px 8px 0px #2dfcfc; padding: 14px 15px; box-sizing: border-box; @@ -49,7 +49,7 @@ span { opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: bold; line-height: normal; @@ -93,7 +93,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 10px; font-weight: 500; line-height: normal; @@ -117,7 +117,7 @@ border-radius: 10px; opacity: 1; - background: #fc872b; + background: #2dfcfc; box-sizing: border-box; border: 1px solid; @@ -130,7 +130,7 @@ span { opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: 500; line-height: normal; @@ -138,7 +138,7 @@ font-variation-settings: "opsz" auto; font-feature-settings: "kern" on; - color: #ffffff; + color: #101010; } } } @@ -165,7 +165,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: bold; line-height: normal; @@ -176,12 +176,33 @@ color: #ffffff; z-index: 0; + + display: flex; + align-items: center; + gap: 4px; + + p { + /* 自动布局子元素 */ + opacity: 1; + + font-family: Space Grotesk; + font-size: 10px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 1; + } } .userinfo_data_des { /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 10px; font-weight: 500; line-height: normal; @@ -209,7 +230,7 @@ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: bold; line-height: normal; @@ -224,9 +245,9 @@ border-radius: 10px; opacity: 1; - background: #fc872b; + background: #2dfcfc; - color: #ffffff; + color: #101010; } } } @@ -257,7 +278,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: bold; line-height: normal; @@ -274,7 +295,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 10px; font-weight: 500; line-height: normal; @@ -282,7 +303,7 @@ font-variation-settings: "opsz" auto; font-feature-settings: "kern" on; - color: #f3be3c; + color: #2dfcfc; z-index: 0; @@ -306,7 +327,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: 500; line-height: normal; @@ -331,7 +352,7 @@ span { opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 12px; font-weight: 500; line-height: normal; @@ -365,7 +386,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 16px; font-weight: bold; line-height: normal; @@ -382,7 +403,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: 500; line-height: normal; @@ -399,7 +420,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 10px; font-weight: 500; line-height: normal; @@ -436,7 +457,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: 500; line-height: normal; @@ -474,7 +495,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 12px; font-weight: 500; line-height: normal; @@ -514,14 +535,14 @@ flex-direction: row; justify-content: center; align-items: center; - padding: 10px 42px; - background: #fc872b; + padding: 10px 0; + background: #2dfcfc; z-index: 0; gap: 10px; box-sizing: border-box; span { /* 自动布局子元素 */ - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: 500; line-height: normal; @@ -530,21 +551,21 @@ font-variation-settings: "opsz" auto; font-feature-settings: "kern" on; - color: #ffffff; + color: #101010; z-index: 0; white-space: nowrap; } .nftToken_content_nft_mint_btn_icon { - width: 24px; - height: 24px; + width: 16px; + height: 16px; } } > span { /* 自动布局子元素 */ - font-family: DM Sans; + font-family: Space Grotesk; font-size: 18px; font-weight: bold; line-height: normal; @@ -570,7 +591,7 @@ span { opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 18px; font-weight: bold; line-height: normal; @@ -596,7 +617,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: bold; line-height: normal; @@ -612,7 +633,7 @@ &:nth-of-type(2) { /* 自动布局子元素 */ - font-family: DM Sans; + font-family: Space Grotesk; font-size: 10px; font-weight: 500; line-height: normal; @@ -620,7 +641,7 @@ font-variation-settings: "opsz" auto; font-feature-settings: "kern" on; - color: #f3be3c; + color: #2dfcfc; z-index: 0; @@ -651,7 +672,7 @@ /* 自动布局子元素 */ opacity: 0.8; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 10px; font-weight: 500; line-height: normal; @@ -668,7 +689,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: 500; line-height: normal; @@ -691,7 +712,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: 500; line-height: normal; @@ -722,7 +743,7 @@ margin-top: 24px; > span { /* 自动布局子元素 */ - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: bold; line-height: normal; @@ -758,7 +779,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: 500; line-height: normal; @@ -775,7 +796,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 16px; font-weight: bold; line-height: normal; diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 88688ba..2d5db22 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,6 +1,6 @@ import classes from "./Home.module.css"; import useUserStore from "@/store/User"; -import { cn, copyText, shortenString } from "@/utils"; +import { cn, copyText, getLevelName, shortenString } from "@/utils"; import { useWeb3Modal } from "@web3modal/wagmi/react"; import { useEffect, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; @@ -11,15 +11,19 @@ import IconFont from "@/components/iconfont"; import { BaseError, useAccount } from "wagmi"; import { config } from "@/components/WalletProvider"; import { createSearchParams, useNavigate } from "react-router-dom"; -import { Button, Dialog, Empty, Toast } from "antd-mobile"; +import { Button, Dialog, Empty, PullToRefresh, Toast } from "antd-mobile"; import { loginOut } from "@/utils/wallet"; -import { api_claim_income, api_get_homepage_user_data } from "@/server/api"; +import { + api_claim_income, + api_get_homepage_user_data, + api_query_user_invitation_code, +} from "@/server/api"; import { UserHomeData } from "@/server/module"; import { UrlQueryParamsKey } from "@/constants"; -import { receiveByContract } from "@/contract/utils"; import usePollingCheckBuyStatus from "@/hook/usePollingCheckBuyStatus"; import { ToastHandler } from "antd-mobile/es/components/toast"; import { disconnect, getAccount } from "@wagmi/core"; +import { PullStatus } from "antd-mobile/es/components/pull-to-refresh"; export default function () { const { Token, UpdateToken } = useUserStore(); const { open } = useWeb3Modal(); @@ -29,13 +33,12 @@ export default function () { const [tabIndex, setTabIndex] = useState(0); const navigate = useNavigate(); const [userData, setUserData] = useState(); + const [inviteCode, setInviteCode] = useState(""); const userInviteLink = useMemo( () => - `${import.meta.env.VITE_BASE_URL}#/?${UrlQueryParamsKey.INVITE_CODE}=${ - userData?.invitationCode || "" - }`, - [userData] + `${location.origin}/#/?${UrlQueryParamsKey.INVITE_CODE}=${inviteCode}`, + [inviteCode] ); const receiveLoadingToast = useRef(); const { @@ -44,8 +47,18 @@ export default function () { stopPollingCheckBuyStatus, } = usePollingCheckBuyStatus("NORMAL"); + const statusRecord: Record = { + pulling: "Pull down to refresh", + canRelease: "Release to refresh immediately", + refreshing: "Loading...", + complete: "Refresh complete", + }; + useEffect(() => { - getHomeData(); + if (Token) { + getHomeData(); + getInviteCode(); + } return () => {}; }, [Token]); @@ -67,6 +80,11 @@ export default function () { setUserData(data?.data); } + async function getInviteCode() { + const { data } = await api_query_user_invitation_code().send({}); + setInviteCode(data?.data.invitationCode || ""); + } + useEffect(() => { console.log("user token:", Token); @@ -75,389 +93,222 @@ export default function () { return ( <> -
-
-
- + { + await getHomeData(); + }} + renderText={(status) => { + return
{statusRecord[status]}
; + }} + disabled={!Token} + > +
+
+
+ - {address ? ( -
-
- {shortenString(address, 6, 4)} - { - const { connector } = getAccount(config); - await disconnect(config, { connector }); - loginOut(); + {address ? ( +
+
+ {shortenString(address, 6, 4)} + { + loginOut(); + setUserData(undefined); + }} + name="tuichu" + className={classes.userinfo_top_right_wallet_disconnect} + color={"#fff"} + /> +
+
+ {userData && ( + <> +
+ {getLevelName(userData.level)} +
+ + )} +
+
+ ) : ( + <> +
{ + open(); }} - name="tuichu" - className={classes.userinfo_top_right_wallet_disconnect} - color={"#fff"} - /> -
-
- {userData && ( - <> -
- {userData.level == 0 && ( - <> - - {t("无等级")} - - )} - {userData.level == 1 && ( - <> - - {userData.active === 0 && ( - {t("普通非活跃")} - )} - {userData.active === 1 && ( - {t("普通活跃")} - )} - - )} - {userData.level == 2 && ( - <> - - {t("社长")} - - )} - {userData.level == 3 && ( - <> - - {t("基金会社长")} - - )} -
- -
{ - navigate("/levelup"); - }} - > - {t("升级")} - -
- - )} -
-
- ) : ( - <> -
{ - open(); - }} - > - {t("链接钱包")} -
- - )} + > + {t("链接钱包")} +
+ + )} +
+
    +
  • + + {userData?.directPushNode || 0} + + + {t("Direct Node")} + +
  • +
  • + + {userData?.teamNode || 0} + + + {t("Team Node")} + +
  • +
  • + + {userData?.revenueUsdt || 0} +

    USDT

    +
    + + {t("Push income")} + +
  • +
-
    -
  • - - {userData?.mintNumber || 0} - - {t("邀请铸造")} -
  • -
  • - - {userData?.presidentNumber || 0} - - {t("团队社长")} -
  • -
  • - - {userData?.airdropNumber || 0} - - {t("邀请空投")} -
  • -
-
-
-
    -
  • setTabIndex(0)} - > - NFT -
  • -
  • setTabIndex(1)} - > - {t("收益")} -
  • -
+
+
    +
  • setTabIndex(0)} + > + NODE +
  • +
-
- {tabIndex == 0 && ( - <> - {address ? ( - <> - {userData?.nftId ? ( -
-
- # {userData?.nftId} - + {tabIndex == 0 && ( + <> + {address ? ( + <> + {userData?.nodeNumber && userData?.nodeNumber > 0 ? ( +
+
+ You own {userData.nodeNumber} nodes + { + navigate("/mint"); + }} + > + {t("Buy Node")} + + +
+ + + {t("Start mining after node subscription ends.")} + +
+ ) : ( +
+
{ navigate("/mint"); }} > - {t("铸造 NFT")} + {t("Buy Node")} - +
+ {t("Buy Edge AI Node.")}
- - - {t("Min结束后按照规则进行空投。")} + )} + + ) : ( + <> +
+ + {t( + "The wallet is not linked and cannot show you the Node." + )}
- ) : ( -
-
+ )} + + )} +
+
+ +
+
+ {t("邀请")} + {address && ( + { + navigate("/invitationlist"); + }} + > + {t("邀请列表")}{" "} + + + )} +
+ +
+ {t("邀请链接")} +
+ {address ? ( + <> + {userData?.nodeNumber && userData?.nodeNumber > 0 ? ( + <> + {shortenString(userInviteLink, 15, 15)} + { - navigate("/mint"); + copyText(userInviteLink); }} - > - {t("铸造 NFT")} - -
- {t("铸造 NFT 获得代币空投")} -
+ className={classes.invite_content_icon} + name="fuzhi" + color={"#fff"} + />{" "} + + ) : ( + <> + + {t("Buy Edge AI Node to get invitation link")} + + )} ) : ( <> -
- {t("钱包未链接,无法向您显示 NFT")} -
+ {t("Link wallet to get invitation link")} )} - - )} - {tabIndex == 1 && ( -
-
- {t("总收益= 已领取 + 待领取")} -
- -
    - {userData?.userIncomes.map((v, i) => ( - { - navigate(`/assetrecord?id=${v.id}&name=${v.coinName}`); - }} - onReceive={async () => { - receiveLoadingToast.current = Toast.show({ - icon: "loading", - duration: 0, - content: t("领取中"), - maskClickable: false, - }); - const { data } = await api_claim_income().send({ - queryParams: { id: v.id }, - }); - const orderInfo = data?.data; - if (!orderInfo?.orderNumber) return; - const buyAmount = BigInt( - orderInfo?.claimQuantity || "" - ); - receiveByContract( - buyAmount, - orderInfo.time, - orderInfo?.orderNumber, - orderInfo.hash - ) - .then((hash) => { - console.log("领取成功!hash:", hash); - getHomeData(); - startPollingCheckBuyStatus(hash); - }) - .catch(async (err: BaseError) => { - receiveLoadingToast.current?.close(); - Toast.show({ - content: err.shortMessage, - icon: "fail", - }); - }); - }} - /> - ))} - - {(userData?.userIncomes.length == 0 || - !userData?.userIncomes) && } -
- )} -
-
-
-
- {t("邀请")} - {address && ( - { - navigate("/invitationlist"); - }} - > - {t("邀请列表")}{" "} - + + {t( + "Invite your friends to become YOTTA nodes and you will get a 20% rebate." + )} - )} -
- -
- {t("邀请链接")} -
- {address ? ( - <> - {userData?.nftId ? ( - <> - {shortenString(userInviteLink, 15, 15)} - { - copyText(userInviteLink); - }} - className={classes.invite_content_icon} - name="fuzhi" - color={"#fff"} - />{" "} - - ) : ( - <> - {t("MINT Nft 获取邀请链接")} - - )} - - ) : ( - <> - {t("链接钱包获取邀请链接")} - - )}
- - - {t( - "普通会员每邀请铸造一个NFT可获得一份空投福利;推荐铸造20个NFT的可升级为会长;团队中拥有20位会长可升级为基金会社长;邀请越多级别越高福利越多。" - )} -
- -
- {t("数据披露")} -
    -
  • - {t("资金池")} - {userData?.pools || 0} -
  • -
  • - {t("社长席位")} - {userData?.president || 0} -
  • -
  • - {t("基金会社长席位")} - {userData?.foundation || 0} -
  • -
-
-
+ ); } - -function ReceiveCom({ - tokenName, - tokenNum, - toReceive, - onAssetRec, - onReceive, -}: { - tokenName: string; - tokenNum: number; - toReceive: number; - onAssetRec: () => void; - onReceive: () => void; -}) { - const { t } = useTranslation(); - return ( -
  • - {tokenName.toUpperCase() == "USDT" && } -
    - - {tokenName} - - - {tokenNum} - - { - onAssetRec(); - }} - > - {t("收益记录")}{" "} - - -
    - -
    -
    - {t("待领取")} - {tokenNum + toReceive} -
    - -
    -
  • - ); -} diff --git a/src/pages/InvitationList.tsx b/src/pages/InvitationList.tsx index afbe7a3..8689cee 100644 --- a/src/pages/InvitationList.tsx +++ b/src/pages/InvitationList.tsx @@ -1,54 +1,50 @@ /* * @LastEditors: John * @Date: 2024-06-19 11:03:01 - * @LastEditTime: 2024-06-25 18:17:18 + * @LastEditTime: 2024-06-27 15:33:01 * @Author: John */ -import { api_preprelion_list } from "@/server/api"; -import { PreprelionListItem } from "@/server/module"; -import { getLevelName } from "@/utils"; -import { Empty } from "antd-mobile"; -import { useEffect, useState } from "react"; +import usePagination from "@/hook/usePagination"; +import { api_recommended_list } from "@/server/api"; +import { RecommendedListItem } from "@/server/module"; +import { Empty, InfiniteScroll } from "antd-mobile"; import DataTable, { TableColumn } from "react-data-table-component"; import { useTranslation } from "react-i18next"; export default function () { const { t } = useTranslation(); - const [data, setData] = useState([]); - const columns: TableColumn[] = [ + const columns: TableColumn[] = [ { name: t("地址"), - selector: (row) => row.address, - grow: 4, + selector: (row) => row.walletAddress, + grow: 9, }, { - name: t("级别"), - grow: 4, - cell(row, rowIndex, column, id) { - return
    {getLevelName(row.level)}
    ; - }, - }, - { - name: t("直推NFT"), - selector: (row) => row.mintNumber, + name: "Node", + selector: (row) => row.nodeNumber, + grow: 1, // @ts-ignore right: "true", - grow: 2, }, ]; - useEffect(() => { - (async () => { - const { data } = await api_preprelion_list().send({}); - setData(data?.data || []); - })(); - - return () => {}; - }, []); + const { list, hasMore, loadMore } = usePagination({ + service({ pageNum, pageSize }) { + return new Promise(async (reslove) => { + const { data } = await api_recommended_list().send({ + queryParams: { pageNum, pageSize }, + }); + reslove(data?.data.records || []); + }); + }, + }); return ( <> - } /> + } /> + + no more data + ); } diff --git a/src/pages/LevelUp.module.css b/src/pages/LevelUp.module.css deleted file mode 100644 index 139a96c..0000000 --- a/src/pages/LevelUp.module.css +++ /dev/null @@ -1,303 +0,0 @@ -.container { - padding: 0 14px; -} - -.LevelUp { - padding-bottom: 32px; - .content { - margin-top: 16px; - .content_box { - display: flex; - justify-content: space-between; - align-items: center; - - .box_item { - /* 自动布局子元素 */ - width: 153px; - height: 90px; - border-radius: 12px; - opacity: 1; - - /* 自动布局 */ - display: flex; - flex-direction: column; - align-items: center; - gap: 7px; - padding: 26px 23px; - - background: #171719; - - box-shadow: 0px 4px 10px 0px rgba(138, 29, 19, 0.3), - inset 0px 0px 6px 0px #8a1d13; - - z-index: 0; - - box-sizing: border-box; - span { - white-space: nowrap; - &:nth-of-type(1) { - /* 自动布局子元素 */ - opacity: 1; - - font-family: DM Sans; - font-size: 10px; - font-weight: 500; - line-height: normal; - letter-spacing: 0em; - - font-variation-settings: "opsz" auto; - font-feature-settings: "kern" on; - color: #4d4d4d; - - z-index: 0; - } - &:nth-of-type(2) { - /* 自动布局子元素 */ - opacity: 1; - - font-family: DM Sans; - font-size: 14px; - font-weight: bold; - line-height: normal; - letter-spacing: 0em; - - font-variation-settings: "opsz" auto; - font-feature-settings: "kern" on; - color: #ffffff; - - z-index: 1; - } - } - } - - .box_arrow { - width: 24px; - height: 24px; - } - } - - .content_price { - display: flex; - align-items: center; - gap: 4px; - margin-top: 16px; - padding: 0 10px; - span { - &:nth-of-type(1) { - /* 自动布局子元素 */ - opacity: 1; - - font-family: DM Sans; - font-size: 10px; - font-weight: 500; - line-height: normal; - letter-spacing: 0em; - - font-variation-settings: "opsz" auto; - font-feature-settings: "kern" on; - color: #ffffff; - - z-index: 0; - } - &:nth-of-type(2) { - /* 自动布局子元素 */ - opacity: 1; - - font-family: DM Sans; - font-size: 10px; - font-weight: bold; - line-height: normal; - letter-spacing: 0em; - - font-variation-settings: "opsz" auto; - font-feature-settings: "kern" on; - color: #fc872b; - - z-index: 1; - } - } - } - - .content_price_des { - display: flex; - flex-direction: column; - gap: 4px; - margin-top: 10px; - padding: 0 10px; - span { - /* 自动布局子元素 */ - opacity: 1; - - font-family: DM Sans; - font-size: 10px; - font-weight: 500; - line-height: normal; - letter-spacing: 0em; - - font-variation-settings: "opsz" auto; - font-feature-settings: "kern" on; - color: #4d4d4d; - - z-index: 1; - } - } - - .content_btn { - /* 自动布局子元素 */ - width: 331px; - height: 40px; - border-radius: 10px; - opacity: 1; - - /* 自动布局 */ - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - padding: 11px 40px; - gap: 10px; - - background: #fc872b; - - z-index: 3; - - box-sizing: border-box; - - margin: 0 auto; - - margin-top: 14px; - - span { - /* 自动布局子元素 */ - opacity: 1; - - font-family: DM Sans; - font-size: 14px; - font-weight: 500; - line-height: normal; - text-align: center; - letter-spacing: 0em; - - font-variation-settings: "opsz" auto; - font-feature-settings: "kern" on; - color: #ffffff; - - z-index: 0; - } - - .icon { - width: 16px; - height: 16px; - } - - &[disabled] { - /* 自动布局子元素 */ - background: #666666; - } - } - } - - .upgrade_conditions { - margin-top: 26px; - > span { - /* 自动布局子元素 */ - opacity: 1; - - font-family: DM Sans; - font-size: 14px; - font-weight: bold; - line-height: normal; - letter-spacing: 0em; - - font-variation-settings: "opsz" auto; - font-feature-settings: "kern" on; - color: #ffffff; - - z-index: 0; - } - > ul { - display: flex; - flex-direction: column; - gap: 14px; - - margin-top: 16px; - > li { - /* 自动布局子元素 */ - width: 344px; - border-radius: 16px; - opacity: 1; - - /* 自动布局 */ - display: flex; - flex-direction: column; - padding: 15px 10px; - - background: #171719; - - z-index: 0; - - gap: 10px; - box-sizing: border-box; - div { - display: flex; - align-items: center; - gap: 6px; - span { - &:nth-of-type(1) { - /* 自动布局子元素 */ - opacity: 1; - - font-family: DM Sans; - font-size: 12px; - font-weight: bold; - line-height: normal; - letter-spacing: 0em; - - font-variation-settings: "opsz" auto; - color: #fc872b; - - z-index: 0; - } - &:nth-of-type(2) { - /* 自动布局子元素 */ - opacity: 1; - - font-family: DM Sans; - font-size: 12px; - font-weight: 500; - line-height: normal; - letter-spacing: 0em; - - font-variation-settings: "opsz" auto; - color: #ffffff; - - z-index: 1; - } - } - } - - > ul { - display: flex; - flex-direction: column; - gap: 4px; - li { - /* 自动布局子元素 */ - opacity: 1; - - font-family: DM Sans; - font-size: 12px; - font-weight: 500; - line-height: normal; - letter-spacing: 0em; - - font-variation-settings: "opsz" auto; - font-feature-settings: "kern" on; - color: #eaeaea; - - z-index: 0; - } - } - } - } - } -} diff --git a/src/pages/LevelUp.tsx b/src/pages/LevelUp.tsx deleted file mode 100644 index 98a2930..0000000 --- a/src/pages/LevelUp.tsx +++ /dev/null @@ -1,275 +0,0 @@ -import IconFont from "@/components/iconfont"; -import classes from "./LevelUp.module.css"; -import { cn, getLevelName } from "@/utils"; -import Button from "antd-mobile/es/components/button"; -import Space from "antd-mobile/es/components/space"; -import { PropsWithChildren, useEffect, useMemo, useRef, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { - api_get_user_upgrade_information, - api_upgrade, - api_users_cancel_orders, -} from "@/server/api"; -import { UpgradeOrder, UserUpgradeInformation } from "@/server/module"; -import Toast, { ToastHandler } from "antd-mobile/es/components/toast"; -import { - authorizedU, - getApproveUsdt, - getBalance, - upGradeByContract, -} from "@/contract/utils"; -import { toWei } from "web3-utils"; -import usePollingCheckBuyStatus from "@/hook/usePollingCheckBuyStatus"; -import { BaseError } from "wagmi"; -import { Dialog } from "antd-mobile"; -import { useNavigate } from "react-router-dom"; -export default function () { - const { t } = useTranslation(); - const navigate = useNavigate(); - const [userUpgradeInfo, setUserUpgradeInfo] = - useState(); - const [approveUsdt, setApproveUsdt] = useState(0n); - const [balance, setBalance] = useState(0n); - const approveLoadingToast = useRef(); - const approvePrice = useMemo( - () => BigInt(toWei(userUpgradeInfo?.price || "0", "ether")), - [userUpgradeInfo?.price] - ); - const upgradeLoadingtoast = useRef(); - const orderInfo = useRef(); - - const { - transcationStatus, - startPollingCheckBuyStatus, - stopPollingCheckBuyStatus, - } = usePollingCheckBuyStatus("NORMAL"); - useEffect(() => { - updateUserUpgrdeInfo(); - return () => {}; - }, []); - - useEffect(() => { - (async () => { - if (userUpgradeInfo?.status != 1) return; - Toast.show({ icon: "loading", content: t("正在获取已授权金额") }); - setBalance(await getBalance()); - setApproveUsdt(await getApproveUsdt()); - Toast.clear(); - })(); - - return () => {}; - }, [userUpgradeInfo?.status]); - - useEffect(() => { - console.log("approvePrice:", approvePrice); - - return () => {}; - }, [approvePrice]); - - useEffect(() => { - if (transcationStatus == "success") { - upgradeLoadingtoast.current?.close(); - stopPollingCheckBuyStatus(); - Dialog.alert({ - content: `${t("升级成功,返回首页查看")}`, - confirmText: "OK", - onConfirm() { - navigate("/"); - }, - }); - } - - return () => {}; - }, [transcationStatus]); - - async function updateUserUpgrdeInfo() { - const { data } = await api_get_user_upgrade_information().send({}); - // setUserUpgradeInfo({ ...data!.data, ...{ status: 1 } }); - setUserUpgradeInfo(data?.data); - } - - return ( - <> -
    -
    -
    -
    - {t("当前级别")} - {getLevelName(userUpgradeInfo?.level || 0)} -
    - -
    - {t("提升级别")} - {userUpgradeInfo?.level == 1 ? t("社长") : t("无")} -
    -
    - -
    - {t("当前升级价格:")} - {userUpgradeInfo?.price || 0} USDT -
    - -
    - {t("价格说明:")} - - {t( - "升级费用xxx USDT起,其中gas费2USDT,剩余部分50%进入资金池,另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加xxx,既第二位社长升级铸造费用为xxxu+xxx*xxx=xxx USDT,以此类推。", - { - value1: userUpgradeInfo?.upgradeFees || 0, - value2: userUpgradeInfo?.proportion || "0%", - value3: - parseFloat(userUpgradeInfo?.upgradeFees || "0") + - (parseFloat(userUpgradeInfo?.upgradeFees || "0") * - parseFloat( - (userUpgradeInfo?.proportion || "0%").replace("%", "") - )) / - 100, - } - )} - -
    - - -
    - -
    - {t("升级条件")} -
      - - - - - -
    -
    -
    - - ); -} - -function ConItem({ - memberName, - limitText, - conList, -}: PropsWithChildren<{ - memberName: string; - limitText: string; - conList: string[]; -}>) { - return ( -
  • -
    - {memberName} - {limitText} -
    -
      - {conList.map((v, i) => ( -
    • {v}
    • - ))} -
    -
  • - ); -} diff --git a/src/pages/Mint.module.css b/src/pages/Mint.module.css index 55660bb..3f8b9e1 100644 --- a/src/pages/Mint.module.css +++ b/src/pages/Mint.module.css @@ -16,7 +16,6 @@ padding: 8px; box-sizing: border-box; - margin-top: 17px; img { width: 100%; height: 100%; @@ -42,7 +41,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: 500; line-height: normal; @@ -59,7 +58,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 16px; font-weight: bold; line-height: normal; @@ -81,12 +80,55 @@ gap: 6px; padding: 0 7px; + margin-top: 20px; span { &:nth-of-type(1) { /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #9e9e9e; + + z-index: 0; + } + + &:nth-of-type(2) { + /* 自动布局子元素 */ + opacity: 1; + + font-family: Space Grotesk; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #eaeaea; + + z-index: 1; + } + } + } + + .price { + display: flex; + align-items: center; + gap: 8px; + + /* 自动布局子元素 */ + > span { + &:nth-of-type(1) { + opacity: 1; + + font-family: Space Grotesk; font-size: 14px; font-weight: 500; line-height: normal; @@ -103,15 +145,55 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; - font-size: 14px; + font-family: Space Grotesk; + font-size: 16px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + + z-index: 1; + } + } + } + + .cost_price { + /* 自动布局子元素 */ + display: flex; + align-items: center; + gap: 8px; + margin-left: auto; + + span { + &:nth-of-type(1) { + font-family: Space Grotesk; + font-size: 10px; font-weight: 500; line-height: normal; letter-spacing: 0em; font-variation-settings: "opsz" auto; font-feature-settings: "kern" on; - color: #eaeaea; + color: #ffffff; + + z-index: 0; + } + + &:nth-of-type(2) { + /* 自动布局子元素 */ + + font-family: Space Grotesk; + font-size: 10px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; z-index: 1; } @@ -120,7 +202,6 @@ .btn { /* 自动布局子元素 */ - width: 331px; height: 40px; border-radius: 10px; opacity: 1; @@ -133,7 +214,7 @@ padding: 11px 40px; gap: 10px; - background: #fc872b; + background: #2dfcfc; z-index: 3; @@ -145,7 +226,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: 500; line-height: normal; @@ -154,7 +235,7 @@ font-variation-settings: "opsz" auto; font-feature-settings: "kern" on; - color: #ffffff; + color: #101010; z-index: 0; } diff --git a/src/pages/Mint.tsx b/src/pages/Mint.tsx index e591a33..923f1f5 100644 --- a/src/pages/Mint.tsx +++ b/src/pages/Mint.tsx @@ -1,10 +1,10 @@ /* * @LastEditors: John * @Date: 2024-06-18 15:28:03 - * @LastEditTime: 2024-06-24 18:28:07 + * @LastEditTime: 2024-06-27 14:35:27 * @Author: John */ -import { cn } from "@/utils"; +import { cn, filterAddressBeforeZero, filterAmountBeforeZero } from "@/utils"; import classes from "./Mint.module.css"; import nft_bg from "@/assets/nft_bg.svg"; import Button from "antd-mobile/es/components/button"; @@ -12,18 +12,24 @@ import Space from "antd-mobile/es/components/space"; import { useTranslation } from "react-i18next"; import { useEffect, useMemo, useRef, useState } from "react"; import { + api_get_homepage_user_data, api_get_nft_configuration_data, - api_nft_order, + api_node_order, api_users_cancel_orders, } from "@/server/api"; -import { NftConfigurationData, NftOrder } from "@/server/module"; +import { + NftConfigurationData, + NftOrder, + NodeOrder, + UserHomeData, +} from "@/server/module"; import { authorizedU, getApproveUsdt, getBalance, payByContract, } from "@/contract/utils"; -import { Dialog, Modal, Toast } from "antd-mobile"; +import { Dialog, Modal, Stepper, Toast } from "antd-mobile"; import useUserStore from "@/store/User"; import usePollingCheckBuyStatus from "@/hook/usePollingCheckBuyStatus"; import { ToastHandler } from "antd-mobile/es/components/toast"; @@ -33,24 +39,31 @@ import { toWei } from "web3-utils"; export default function () { const { t } = useTranslation(); const { Token } = useUserStore(); - const [nftConfig, setNftConfig] = useState(); + const [nodeConfig, setNodeConfig] = useState(); const [approveUsdt, setApproveUsdt] = useState(0n); const [balance, setBalance] = useState(0n); - const orderInfo = useRef(); + const orderInfo = useRef(); const navigate = useNavigate(); + const [num, setNum] = useState(1); const buyLoadingToast = useRef(); const approveLoadingToast = useRef(); - const { buyNftIds, startPollingCheckBuyStatus, stopPollingCheckBuyStatus } = - usePollingCheckBuyStatus("NFT"); + const { + transcationStatus, + startPollingCheckBuyStatus, + stopPollingCheckBuyStatus, + } = usePollingCheckBuyStatus("NORMAL"); - const approvePrice = useMemo( - () => BigInt(toWei(nftConfig?.nftPrice || "0", "ether")), - [nftConfig?.nftPrice] + const costNum = useMemo( + () => + BigInt( + toWei(`${parseFloat(`${nodeConfig?.nodePrice || "0"}`) * num}`, "ether") + ), + [nodeConfig?.nodePrice, num] ); useEffect(() => { - updateNftConfig(); + updateNodeConfig(); return () => {}; }, []); @@ -66,16 +79,18 @@ export default function () { return () => {}; }, [Token]); - async function updateNftConfig() { - const { data } = await api_get_nft_configuration_data().send({}); - setNftConfig(data?.data); + async function updateNodeConfig() { + const { data } = await api_get_homepage_user_data().send({}); + setNodeConfig(data?.data); } useEffect(() => { - if (buyNftIds) { + if (transcationStatus == "success") { buyLoadingToast.current?.close(); stopPollingCheckBuyStatus(); Dialog.alert({ - content: `${t("MINT成功,返回首页查看")}`, + content: `${t( + "Buy successful. Please return to the homepage to view." + )}`, confirmText: "OK", onConfirm() { navigate("/"); @@ -84,7 +99,7 @@ export default function () { } return () => {}; - }, [buyNftIds]); + }, [transcationStatus]); useEffect(() => { return () => {}; @@ -93,48 +108,41 @@ export default function () { return ( <>
    +
    + + Introduction to the node Introduction to the node Inion to the node + Introduction to the node Introduction to the node Introduction to + the node Introduction to the node Introduction to the node + Introduction to the node Introduction to the node Introduction to + the node Introduction to the node Introduction to the node + Introduction to the node + +
    -
      -
    • - {t("NFT总量:")} - {nftConfig?.nftCount || 0} -
    • +
      + Price: + {nodeConfig?.nodePrice} USDT +
      -
    • - {t("MINT余量:")} - {nftConfig?.nftRemainder || 0} -
    • + { + if (value <= 0) return; + setNum(value); + }} + style={{ + "--button-text-color": "#101010", + }} + /> -
    • - {t("当前MINT价格:")} - {nftConfig?.nftPrice || 0} USDT -
    • -
    - -
    - {t("价格说明:")} +
    + Cost: - {t( - "{{value1}} USDT起,每增加 {{value2}} 名普通会员,NFT价格上涨 {{value3}},既:前 {{value2}} 名价格为 {{value1}} USDT/枚,value4 名价格为{{value1}}u+{{value1}}u*{{value3}}={{value5}} USDT/枚,以此类推。", - { - value1: nftConfig?.initialPrice || 0, - value2: nftConfig?.floatingQuantity || 0, - value3: nftConfig?.kamibutsu || "0%", - value4: `${ - parseInt(nftConfig?.floatingQuantity || "0") + 1 - } - ${parseInt(nftConfig?.floatingQuantity || "0") * 2}`, - value5: - parseFloat(nftConfig?.initialPrice || "0") + - (parseFloat(nftConfig?.initialPrice || "0") * - parseFloat( - (nftConfig?.kamibutsu || "0%").replace("%", "") - )) / - 100, - } - )} + {parseFloat(`${nodeConfig?.nodePrice || "0"}`) * num} USDT
    @@ -154,7 +162,7 @@ export default function () { duration: 0, content: t("正在授权USDT"), }); - authorizedU(approvePrice) + authorizedU(costNum) .then(async () => { setApproveUsdt(await getApproveUsdt()); approveLoadingToast.current?.close(); @@ -173,18 +181,46 @@ export default function () { content: t("购买中"), maskClickable: false, }); - const { data: orderRes } = await api_nft_order().send({}); + const { data: orderRes } = await api_node_order().send({ + data: { + number: num, + }, + }); orderInfo.current = orderRes?.data; if (!orderInfo.current?.orderNumber) return; - const buyAmount = BigInt(orderInfo.current?.buyAmount || ""); + const { + collectionAddress, + collectionAmount, + addressOne, + addressTwo, + addressThree, + addressFour, + awardOne, + awardTwo, + awardThree, + awardFour, + } = orderInfo.current; payByContract( - buyAmount, - orderInfo.current?.orderNumber, - orderInfo.current.payInduction + filterAddressBeforeZero([ + collectionAddress, + addressOne, + addressTwo, + addressThree, + addressFour, + ]), + filterAmountBeforeZero([ + BigInt(toWei(`${collectionAmount}`, "ether")), + BigInt(toWei(`${awardOne}`, "ether")), + BigInt(toWei(`${awardTwo}`, "ether")), + BigInt(toWei(`${awardThree}`, "ether")), + BigInt(toWei(`${awardFour}`, "ether")), + ]), + orderInfo.current.orderNumber, + orderInfo.current.time ) .then((hash) => { console.log("购买成功!hash:", hash); - updateNftConfig(); + updateNodeConfig(); startPollingCheckBuyStatus(hash); }) .catch(async (err: BaseError) => { @@ -194,14 +230,14 @@ export default function () { icon: "fail", }); // 取消购买 - await api_users_cancel_orders().send({ - queryParams: { orderId: orderInfo.current?.id! }, - }); + // await api_users_cancel_orders().send({ + // queryParams: { orderId: orderInfo.current?.id! }, + // }); }); }} > - {approveUsdt > 0n && MINT} + {approveUsdt > 0n && Buy} {approveUsdt === 0n && {t("授权USDT")}} diff --git a/src/server/api.ts b/src/server/api.ts index 76cdfaa..95576ce 100644 --- a/src/server/api.ts +++ b/src/server/api.ts @@ -1,7 +1,7 @@ /* * @LastEditors: John * @Date: 2024-06-18 10:28:21 - * @LastEditTime: 2024-06-25 14:47:34 + * @LastEditTime: 2024-06-27 09:52:45 * @Author: John */ import { GET, POST } from "./client"; @@ -11,7 +11,9 @@ import { IncomeRecordType, NftConfigurationData, NftOrder, + NodeOrder, PreprelionListItem, + RecommendedList, UpgradeOrder, UserHomeData, UserIncome, @@ -20,7 +22,7 @@ import { // 检查账号是否注册 export function api_check_account_registration() { - return GET<{ account: string }, { exist: boolean }>({ + return GET<{ account: string; chainType: 2 }, { exist: boolean }>({ url: "/api/account/exist", requiresToken: false, }); @@ -69,9 +71,7 @@ export function api_get_wallet_signature_string() { // 获取首页用户数据 export function api_get_homepage_user_data() { return GET({ - url: "/api/common/getUserData", - requiresToken: false, - requiresAddress: false, + url: "/api/user-node/getHomeData", }); } @@ -106,8 +106,8 @@ export function api_pagling_query_income_record() { } // NFT下单 -export function api_nft_order() { - return POST({ url: "/api/nft/payNft" }); +export function api_node_order() { + return POST<{ number: number }, NodeOrder>({ url: "/api/user-node/payNode" }); } // 用户取消订单告诉我 @@ -115,9 +115,11 @@ export function api_users_cancel_orders() { return POST({ url: "/api/nft/cancel" }); } -// 直推列表 -export function api_preprelion_list() { - return GET({ url: "/api/user/getDirectPushList" }); +// 推荐列表 +export function api_recommended_list() { + return GET<{ pageNum: number; pageSize: number }, RecommendedList>({ + url: "/api/user-node/recommendedLists", + }); } // 升级 @@ -145,3 +147,10 @@ export function api_query_whether_the_user_is_binding_relationship() { url: "/api/account/bindOrNot", }); } + +// 查询用户邀请码 +export function api_query_user_invitation_code() { + return GET({ + url: "/api/invite/invitationCode", + }); +} diff --git a/src/server/module.d.ts b/src/server/module.d.ts index 56317fa..27425c6 100644 --- a/src/server/module.d.ts +++ b/src/server/module.d.ts @@ -5,21 +5,16 @@ export type BASE_RESPONSE = { timeMillis: number; }; // What's returned from request -export type Level = 0 | 1 | 2 | 3; // 0=无等级 1=会员 2=社长 3=基金会 +export type Level = 0 | 1 | 2 | 3 | 4; // 0=无等级 1=区代理 2=市代理 3=省代理 4=超级节点 export interface UserHomeData { address: string; - airdropNumber: number; - foundation: number; - invitationCode: string; + directPushNode: number; level: Level; - mintNumber: number; - nftId: number; - pools: string; - president: number; - presidentNumber: number; + nodeNumber: number; + nodePrice: string; + revenueUsdt: string; + teamNode: number; userImg: string; - userIncomes: UserIncome[]; - active: 0 | 1; // "0=非活跃 1=活跃用户" } export interface UserIncome { coinId: number; @@ -137,3 +132,52 @@ export interface ClaimIncome { orderNumber: string; time: number; } + +export interface RecommendedList { + countId: string; + current: number; + maxLimit: string; + optimizeCountSql: boolean; + orders: Order[]; + pages: number; + records: RecommendedListItem[]; + searchCount: boolean; + size: number; + total: number; +} +export interface RecommendedListItem { + walletAddress: string; + nodeNumber: number; + promotionUsdt: string; + nodeCount: number; +} + +export interface NodeOrder { + time: number; + addressFour: string; + addressOne: string; + addressThree: string; + addressTwo: string; + awardFour: string; + awardOne: string; + awardThree: string; + awardTwo: string; + buyAmount: string; + collectionAddress: string; + collectionAmount: string; + createBy: string; + createTime: number; + dataJson: string; + hash: string; + id: number; + illustrate: string; + nodeNumber: number; + nodeSettingId: number; + orderNumber: string; + payCoin: string; + status: number; + updateBy: string; + updateTime: string; + userId: number; + walletAddress: string; +} diff --git a/src/style/ant-cover-m.css b/src/style/ant-cover-m.css index 03be39d..fa8a2f0 100644 --- a/src/style/ant-cover-m.css +++ b/src/style/ant-cover-m.css @@ -3,13 +3,13 @@ border-bottom: 0.25px solid #333333; .adm-tabs-tab-line { - background-color: #fc872b; + background-color: #2dfcfc; } .adm-tabs-tab { opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: 500; line-height: normal; @@ -51,7 +51,7 @@ opacity: 1; box-sizing: border-box; - border: 1px solid #fc872b; + border: 1px solid #2dfcfc; z-index: 1; background-color: transparent; @@ -59,7 +59,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 10px; font-weight: 500; line-height: 25px; @@ -80,14 +80,14 @@ border-radius: 8px; opacity: 1; - background: #fc872b; + background: #2dfcfc; z-index: 0; /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 10px; font-weight: 500; line-height: 25px; @@ -111,7 +111,7 @@ .adm-picker-header-title { opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 17px; font-weight: bold; line-height: 24px; @@ -124,7 +124,7 @@ .adm-picker-header-button { opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 17px; font-weight: 500; line-height: 24px; @@ -147,7 +147,7 @@ .adm-picker-view-column-item { /* height: 34px; */ .adm-picker-view-column-item-label { - /* font-family: DM Sans; + /* font-family: Space Grotesk; font-size: 16px; font-weight: 500; line-height: 34px; @@ -192,7 +192,7 @@ /* background: rgba(252, 135, 43, 0.5) !important; */ box-sizing: border-box !important; - border: 1px solid #fc872b !important; + border: 1px solid #2dfcfc !important; /* backdrop-filter: blur(10px); */ @@ -200,7 +200,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: 500; line-height: normal; @@ -240,7 +240,7 @@ /* 自动布局子元素 */ opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: normal; line-height: normal; @@ -256,3 +256,104 @@ } } } + +/* adm-stepper */ +.adm-stepper { + width: calc(100%) !important; + height: 42px; + border-radius: 5px !important; + opacity: 1; + background: rgba(37, 33, 39, 0.2); + box-sizing: border-box !important; + border: 1px solid #2dfcfc !important; + .adm-button { + width: 42px; + height: 42px; + border-radius: 5px; + opacity: 1; + + background: #2dfcfc; + + svg { + width: 23px; + height: 23px; + } + } + + .adm-stepper-middle { + .adm-stepper-input { + height: 44px; + background-color: transparent; + + .adm-input-element { + opacity: 1; + + font-family: Space Grotesk; + font-size: 22px; + font-weight: bold; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #ffffff; + } + } + } +} + +.adm-dialog { + .adm-center-popup-body { + box-sizing: border-box !important; + border: 1px solid #2dfcfc !important; + border-radius: 10px !important; + background-color: transparent !important; + backdrop-filter: blur(10px); + .adm-dialog-content { + .adm-auto-center-content { + opacity: 1; + + font-family: Space Grotesk; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0px; + + font-variation-settings: "opsz" auto; + color: #ffffff; + + z-index: 0; + } + } + + .adm-dialog-footer { + .adm-dialog-action-row { + border-top: 1px solid #2dfcfc !important; + + .adm-dialog-button { + span { + color: #2dfcfc; + } + } + } + } + } +} + +/* adm-pull-to-refresh */ +.adm-pull-to-refresh { + .adm-pull-to-refresh-head-content { + /* 自动布局子元素 */ + font-family: Space Grotesk; + font-size: 14px; + font-weight: 500; + line-height: normal; + letter-spacing: 0em; + + font-variation-settings: "opsz" auto; + font-feature-settings: "kern" on; + color: #9e9e9e; + + z-index: 0; + } +} diff --git a/src/style/react-data-table-component-cover-m.css b/src/style/react-data-table-component-cover-m.css index 9054f4a..c3281b5 100644 --- a/src/style/react-data-table-component-cover-m.css +++ b/src/style/react-data-table-component-cover-m.css @@ -16,7 +16,7 @@ div { opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 12px; font-weight: 500; line-height: normal; @@ -41,7 +41,7 @@ div { opacity: 1; - font-family: DM Sans; + font-family: Space Grotesk; font-size: 14px; font-weight: bold; line-height: normal; diff --git a/src/utils/index.ts b/src/utils/index.ts index f72c18e..e74f9a9 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,7 +1,7 @@ /* * @LastEditors: John * @Date: 2024-06-17 18:19:27 - * @LastEditTime: 2024-06-25 15:29:51 + * @LastEditTime: 2024-06-27 11:40:59 * @Author: John */ import { type ClassValue, clsx } from "clsx"; @@ -87,14 +87,37 @@ export function cn(...inputs: ClassValue[]) { export function getLevelName(level: Level) { switch (level) { case 0: - return i18next.t("普通非活跃"); + return "No Node"; case 1: - return i18next.t("普通活跃"); + return "Regional agent"; case 2: - return i18next.t("社长"); + return "Municipal agent"; case 3: - return i18next.t("基金会社长"); + return "Provincial agent"; + case 4: + return "Super Node"; default: break; } } + +export function filterAddressBeforeZero(arr: string[]) { + let result = []; + for (let i = 0; i < arr.length; i++) { + if (arr[i] === "0") { + break; + } + result.push(arr[i]); + } + return result; +} +export function filterAmountBeforeZero(arr: bigint[]) { + let result = []; + for (let i = 0; i < arr.length; i++) { + if (arr[i] === 0n) { + break; + } + result.push(arr[i]); + } + return result; +} diff --git a/src/utils/wallet.ts b/src/utils/wallet.ts index 1e2910f..91807a5 100644 --- a/src/utils/wallet.ts +++ b/src/utils/wallet.ts @@ -1,7 +1,7 @@ /* * @LastEditors: John * @Date: 2024-06-19 15:55:07 - * @LastEditTime: 2024-06-25 14:47:58 + * @LastEditTime: 2024-06-27 15:09:45 * @Author: John */ import { config } from "@/components/WalletProvider"; @@ -89,7 +89,7 @@ export async function signAndLogin(address?: `0x${string}`): Promise { }); const { data: isExitData } = await api_check_account_registration().send({ - queryParams: { account: address }, + queryParams: { account: address, chainType: 2 }, }); if (isExitData?.data?.exist) { // 登录 @@ -106,8 +106,6 @@ export async function signAndLogin(address?: `0x${string}`): Promise { }); } catch (error) { // 用户拒绝签名或者遇到错误,断开链接 - const { connector } = getAccount(config); - await disconnect(config, { connector }); loadingToast.close(); loginOut(); throw new Error("用户拒绝签名或者遇到错误,断开链接"); @@ -128,32 +126,24 @@ export async function signAndLogin(address?: `0x${string}`): Promise { return { ...state, Token: loginInfoData.data?.token }; }); - // TODO 判断用户是否绑定关系✔ - const { data } = - await api_query_whether_the_user_is_binding_relationship().send({}); - if ( - typeof data?.data.result == "boolean" && - data?.data.result === false - ) { - const inviteCode = getUrlQueryParam(UrlQueryParamsKey.INVITE_CODE); - if (inviteCode) { - const { data } = await api_binding_invitation_relationship().send({ - data: { - shareCode: inviteCode, - }, - }); - } - } reslove(); loadingToast.close(); } } else { + const inviteCode = getUrlQueryParam(UrlQueryParamsKey.INVITE_CODE); + if (!inviteCode) { + Toast.show({ + icon: "fail", + content: i18next.t("invalid invitation link"), + }); + return loginOut(); + } // 注册 await api_signUp().send({ data: { account: address, publicKey, - shareCode: "", + shareCode: inviteCode, chainType: 2, }, }); @@ -164,7 +154,9 @@ export async function signAndLogin(address?: `0x${string}`): Promise { }); } -export function loginOut() { +export async function loginOut() { + const { connector } = getAccount(config); + await disconnect(config, { connector }); useUserStore.setState((state) => { return { ...state, Address: "", Token: "" }; }); diff --git a/vite.config.ts b/vite.config.ts index 7acc4e3..55e06ef 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,7 +1,7 @@ /* * @LastEditors: John * @Date: 2024-06-17 17:20:03 - * @LastEditTime: 2024-06-24 10:08:56 + * @LastEditTime: 2024-06-26 17:50:12 * @Author: John */ import { defineConfig } from "vite"; @@ -16,7 +16,7 @@ export default defineConfig({ host: "192.168.10.167", proxy: { "/dev": { - target: "http://192.168.10.106:8100", + target: "http://192.168.10.106:8102", changeOrigin: true, rewrite: (path) => path.replace(/^\/dev/, ""), },