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 188957b..0000000 Binary files a/src/assets/font/DMSans_18pt-Medium.ttf and /dev/null differ diff --git a/src/assets/font/SpaceGrotesk-Medium.ttf b/src/assets/font/SpaceGrotesk-Medium.ttf new file mode 100644 index 0000000..7d44b66 Binary files /dev/null and b/src/assets/font/SpaceGrotesk-Medium.ttf differ 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/, ""), },