Compare commits

...

10 Commits

Author SHA1 Message Date
john 61df3f063a 🐞 fix: 2024-07-20 10:37:59 +08:00
john 562a95ca9c feat: 2024-07-19 19:33:51 +08:00
john 29a6ea86c1 feat: 2024-07-18 18:49:30 +08:00
john 4a230d7791 feat: 2024-07-10 18:13:03 +08:00
john 8cbbb04513 🐞 fix:
更换合约
2024-07-03 18:29:35 +08:00
john aff0f68989 🐞 fix: 2024-07-02 18:41:27 +08:00
john f6cd16f1c6 🐞 fix:
修改部分文案
2024-06-27 18:29:40 +08:00
john 007af1f625 🐞 fix:
修复已知问题
2024-06-26 15:02:28 +08:00
john 20b2185e51 🐞 fix:
修改翻译
2024-06-25 11:36:06 +08:00
john b51f160150 feat:
添加测试环境
2024-06-24 18:55:23 +08:00
33 changed files with 1629 additions and 789 deletions

View File

@ -1,12 +1,19 @@
###
# @LastEditors: John
# @Date: 2024-07-02 11:31:07
# @LastEditTime: 2024-07-10 15:25:12
# @Author: John
###
### ###
# @LastEditors: John # @LastEditors: John
# @Date: 2024-06-18 10:12:21 # @Date: 2024-06-18 10:12:21
# @LastEditTime: 2024-06-24 18:25:07 # @LastEditTime: 2024-07-02 16:46:51
# @Author: John # @Author: John
### ###
VITE_BASE_URL=http://192.168.10.167:5173/ VITE_BASE_URL=
VITE_BASE_API_URL=/dev VITE_BASE_API_URL=/dev
VITE_PARTICIPATE_CHAIN_ID=97 VITE_PARTICIPATE_CHAIN_ID=97
VITE_PURCHASED_CONTRACT_ADDRESS=0xD70762bf8682b68bd0cbbBC0cdeC81db4f00AEc6 VITE_PURCHASED_CONTRACT_ADDRESS=0xcA03e32ab7731cD721239A7AD24f3d185e4d63CD
VITE_NETWORK_USDT_ADDRESS=0xf9A18B7FC8Eb118f8Ad59fBD6eb1A181eaCb4E63 VITE_RECEIVE_RAMB_CONTRACT_ADDRESS=0x944fBF12c9b77BFfFA223CE1568F28820d319c2F
VITE_NETWORK_USDT_ADDRESS=0x6d528B0a62f8cDdf4B3F6961D70F4f4a18a92A0D
VITE_CHECK_TRANSACTION_DETAILS_URL=https://testnet.bscscan.com/ VITE_CHECK_TRANSACTION_DETAILS_URL=https://testnet.bscscan.com/

View File

@ -1,6 +1,13 @@
###
# @LastEditors: John
# @Date: 2024-07-02 11:31:07
# @LastEditTime: 2024-07-19 14:39:15
# @Author: John
###
VITE_BASE_URL=/ VITE_BASE_URL=/
VITE_BASE_API_URL=/dev VITE_BASE_API_URL=
VITE_PARTICIPATE_CHAIN_ID=56 VITE_PARTICIPATE_CHAIN_ID=56
VITE_PURCHASED_CONTRACT_ADDRESS= VITE_PURCHASED_CONTRACT_ADDRESS=0xb8D623B24b6A9B7044C078B80c90B292e5b2ee13
VITE_NETWORK_USDT_ADDRESS= VITE_RECEIVE_RAMB_CONTRACT_ADDRESS=0x40b07C2944390f11bc14acF89710Bd7228Aca9bE
VITE_NETWORK_USDT_ADDRESS=0x55d398326f99059fF775485246999027B3197955
VITE_CHECK_TRANSACTION_DETAILS_URL=https://bscscan.com/ VITE_CHECK_TRANSACTION_DETAILS_URL=https://bscscan.com/

13
.env.test Normal file
View File

@ -0,0 +1,13 @@
###
# @LastEditors: John
# @Date: 2024-06-24 18:38:45
# @LastEditTime: 2024-07-18 18:43:53
# @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=0xdccBd0FbFd51dA16AEDc8b1985f3eFDA3F380944
VITE_RECEIVE_RAMB_CONTRACT_ADDRESS=0x944fBF12c9b77BFfFA223CE1568F28820d319c2F
VITE_NETWORK_USDT_ADDRESS=0x6d528B0a62f8cDdf4B3F6961D70F4f4a18a92A0D
VITE_CHECK_TRANSACTION_DETAILS_URL=https://testnet.bscscan.com/

View File

@ -1,5 +1,5 @@
{ {
"symbol_url": "//at.alicdn.com/t/c/font_4589567_vzk80gocu8s.js", "symbol_url": "//at.alicdn.com/t/c/font_4589567_u5yhe33hzt.js",
"use_typescript": true, "use_typescript": true,
"save_dir": "./src/components/iconfont", "save_dir": "./src/components/iconfont",
"trim_icon_prefix": "icon", "trim_icon_prefix": "icon",

View File

@ -6,6 +6,7 @@
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "tsc && vite build", "build": "tsc && vite build",
"build:test": "tsc && vite build --mode test",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview", "preview": "vite preview",
"iconfont": "npx iconfont-h5" "iconfont": "npx iconfont-h5"

View File

@ -19,7 +19,7 @@ import InvitationList from "./pages/InvitationList";
import { useEffect } from "react"; import { useEffect } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import useUserStore from "./store/User"; import useUserStore from "./store/User";
import { getUrlQueryParam } from "./utils"; import { getUrlParameterByName } from "./utils";
import { UrlQueryParamsKey } from "./constants"; import { UrlQueryParamsKey } from "./constants";
import { signAndLogin } from "./utils/wallet"; import { signAndLogin } from "./utils/wallet";
import { useAccount } from "wagmi"; import { useAccount } from "wagmi";
@ -29,7 +29,9 @@ function App() {
const { address } = useAccount(); const { address } = useAccount();
useEffect(() => { useEffect(() => {
i18n.changeLanguage(currantLang); i18n.changeLanguage(currantLang);
UpdateInviteCode(getUrlQueryParam(UrlQueryParamsKey.INVITE_CODE) || ""); UpdateInviteCode(
getUrlParameterByName(UrlQueryParamsKey.INVITE_CODE) || ""
);
return () => {}; return () => {};
}, []); }, []);

View File

@ -1,7 +1,7 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-06-18 15:16:31 * @Date: 2024-06-18 15:16:31
* @LastEditTime: 2024-06-19 18:30:52 * @LastEditTime: 2024-06-26 14:49:22
* @Author: John * @Author: John
*/ */
import Picker, { import Picker, {
@ -42,7 +42,7 @@ export default function () {
case "/levelup": case "/levelup":
return t("级别提升"); return t("级别提升");
case "/assetrecord": case "/assetrecord":
return t("资产记录"); return t("收益记录");
case "/airdroprecord": case "/airdroprecord":
return t("RMOB记录"); return t("RMOB记录");
case "/invitationlist": case "/invitationlist":
@ -57,7 +57,7 @@ export default function () {
<div className={classes.header}> <div className={classes.header}>
<div className={classes.header_top}> <div className={classes.header_top}>
<img className={classes.header_logo} src={logo} alt="" /> <img className={classes.header_logo} src={logo} alt="" />
<span className={classes.header_title}>{t("红魔NFT")}</span> <span className={classes.header_title}>{t("红魔股权NFT")}</span>
<Popover.Menu <Popover.Menu
mode="dark" mode="dark"
actions={langColums} actions={langColums}
@ -118,48 +118,6 @@ export default function () {
</div> </div>
)} )}
</div> </div>
{/*
<Picker
// title={t("选择语言")}
columns={langColums}
visible={langPickVisble}
onClose={() => {
setLangPickVisble(false);
}}
value={langPickValue}
onConfirm={(v) => {
setLangPickValue(v);
// console.log("Current lang:", v[0]);
switch (v[0]) {
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;
}
// console.log("i18n lang:", i18n.language);
}}
confirmText={t("确定")}
cancelText={t("取消")}
/> */}
</> </>
); );
} }

View File

@ -1,7 +1,7 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-06-17 18:01:43 * @Date: 2024-06-17 18:01:43
* @LastEditTime: 2024-06-17 18:16:57 * @LastEditTime: 2024-06-24 18:51:52
* @Author: John * @Author: John
*/ */
/* /*
@ -39,9 +39,10 @@ const metadata = {
icons: [`${import.meta.env.BASE_URL}/favicon.svg`], icons: [`${import.meta.env.BASE_URL}/favicon.svg`],
}; };
let chains = import.meta.env.PROD let chains =
? ([bsc] as const) import.meta.env.DEV || import.meta.env.MODE == "test"
: ([bnbTestNetwork] as const); ? ([bnbTestNetwork] as const)
: ([bsc] as const);
export const config = defaultWagmiConfig({ export const config = defaultWagmiConfig({
chains, // required chains, // required

View File

@ -0,0 +1,33 @@
/* tslint:disable */
/* eslint-disable */
import React, { CSSProperties, SVGAttributes, FunctionComponent } from 'react';
import { getIconColor } from './helper';
interface Props extends Omit<SVGAttributes<SVGElement>, 'color'> {
size?: number;
color?: string | string[];
}
const DEFAULT_STYLE: CSSProperties = {
display: 'block',
};
const IconTransfer: FunctionComponent<Props> = ({ size = 18, color, style: _style, ...rest }) => {
const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE;
return (
<svg viewBox="0 0 1024 1024" width={size + 'px'} height={size + 'px'} style={style} {...rest}>
<path
d="M85.346462 170.653538c0-47.104 38.203077-85.307077 85.307076-85.307076H512c47.143385 0 85.346462 38.203077 85.346462 85.307076v170.692924c0 47.104-38.203077 85.307077-85.346462 85.307076H170.653538a85.346462 85.346462 0 0 1-85.307076-85.307076V170.653538zM426.653538 682.653538c0-47.104 38.203077-85.307077 85.346462-85.307076h341.346462c47.104 0 85.307077 38.203077 85.307076 85.307076v170.692924c0 47.104-38.203077 85.307077-85.307076 85.307076H512a85.346462 85.346462 0 0 1-85.346462-85.307076v-170.692924z"
fill={getIconColor(color, 0, '#666666')}
/>
<path
d="M879.064615 287.980308l-30.72 30.72a32.019692 32.019692 0 0 0 45.292308 45.292307l55.138462-55.177846c29.184-29.144615 29.184-76.445538 0-105.629538l-55.138462-55.138462a32.019692 32.019692 0 0 0-45.292308 45.252923l30.72 30.72h-196.411077a32.019692 32.019692 0 0 0 0 63.960616h196.450462zM144.935385 799.980308l30.72 30.72a32.019692 32.019692 0 0 1-45.292308 45.292307l-55.138462-55.177846c-29.184-29.144615-29.184-76.445538 0-105.629538l55.138462-55.138462a32.019692 32.019692 0 0 1 45.292308 45.252923l-30.72 30.72h196.411077a32.019692 32.019692 0 0 1 0 63.960616H144.896z"
fill={getIconColor(color, 1, '#FFFFFF')}
/>
</svg>
);
};
export default IconTransfer;

View File

@ -2,6 +2,7 @@
/* eslint-disable */ /* eslint-disable */
import React, { SVGAttributes, FunctionComponent } from 'react'; import React, { SVGAttributes, FunctionComponent } from 'react';
import IconTransfer from './IconTransfer';
import IconDiqiu from './IconDiqiu'; import IconDiqiu from './IconDiqiu';
import IconTuichu from './IconTuichu'; import IconTuichu from './IconTuichu';
import IconChevronsrightshuangyoujiantou from './IconChevronsrightshuangyoujiantou'; import IconChevronsrightshuangyoujiantou from './IconChevronsrightshuangyoujiantou';
@ -11,6 +12,7 @@ import IconTongdun from './IconTongdun';
import IconJindun from './IconJindun'; import IconJindun from './IconJindun';
import IconXingdun from './IconXingdun'; import IconXingdun from './IconXingdun';
import IconGuanjun from './IconGuanjun'; import IconGuanjun from './IconGuanjun';
export { default as IconTransfer } from './IconTransfer';
export { default as IconDiqiu } from './IconDiqiu'; export { default as IconDiqiu } from './IconDiqiu';
export { default as IconTuichu } from './IconTuichu'; export { default as IconTuichu } from './IconTuichu';
export { default as IconChevronsrightshuangyoujiantou } from './IconChevronsrightshuangyoujiantou'; export { default as IconChevronsrightshuangyoujiantou } from './IconChevronsrightshuangyoujiantou';
@ -21,7 +23,7 @@ export { default as IconJindun } from './IconJindun';
export { default as IconXingdun } from './IconXingdun'; export { default as IconXingdun } from './IconXingdun';
export { default as IconGuanjun } from './IconGuanjun'; export { default as IconGuanjun } from './IconGuanjun';
export type IconNames = 'diqiu' | 'tuichu' | 'chevronsrightshuangyoujiantou' | 'fuzhi' | 'icon_arrow_left' | 'tongdun' | 'jindun' | 'xingdun' | 'guanjun'; export type IconNames = 'transfer' | 'diqiu' | 'tuichu' | 'chevronsrightshuangyoujiantou' | 'fuzhi' | 'icon_arrow_left' | 'tongdun' | 'jindun' | 'xingdun' | 'guanjun';
interface Props extends Omit<SVGAttributes<SVGElement>, 'color'> { interface Props extends Omit<SVGAttributes<SVGElement>, 'color'> {
name: IconNames; name: IconNames;
@ -31,6 +33,8 @@ interface Props extends Omit<SVGAttributes<SVGElement>, 'color'> {
const IconFont: FunctionComponent<Props> = ({ name, ...rest }) => { const IconFont: FunctionComponent<Props> = ({ name, ...rest }) => {
switch (name) { switch (name) {
case 'transfer':
return <IconTransfer {...rest} />;
case 'diqiu': case 'diqiu':
return <IconDiqiu {...rest} />; return <IconDiqiu {...rest} />;
case 'tuichu': case 'tuichu':

View File

@ -1,9 +1,43 @@
[ [
{
"inputs": [
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "orderId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "paymentType",
"type": "uint256"
},
{
"internalType": "string",
"name": "NFTURI",
"type": "string"
}
],
"name": "buyEquityNFT",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{ {
"inputs": [ "inputs": [
{ {
"internalType": "address", "internalType": "address",
"name": "hongMoAddr", "name": "EquityNFTAddr",
"type": "address" "type": "address"
}, },
{ {
@ -15,11 +49,6 @@
"internalType": "address", "internalType": "address",
"name": "p1", "name": "p1",
"type": "address" "type": "address"
},
{
"internalType": "address",
"name": "p2",
"type": "address"
} }
], ],
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
@ -73,6 +102,12 @@
"internalType": "uint256", "internalType": "uint256",
"name": "orderId", "name": "orderId",
"type": "uint256" "type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "paymentType",
"type": "uint256"
} }
], ],
"name": "BuySuccess", "name": "BuySuccess",
@ -97,169 +132,6 @@
"name": "OwnershipTransferred", "name": "OwnershipTransferred",
"type": "event" "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": [], "inputs": [],
"name": "renounceOwnership", "name": "renounceOwnership",
@ -295,6 +167,55 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
}, },
{
"inputs": [
{
"internalType": "address",
"name": "addr",
"type": "address"
},
{
"internalType": "string",
"name": "NFTURI",
"type": "string"
}
],
"name": "rewardNFT",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"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"
},
{ {
"inputs": [ "inputs": [
{ {
@ -314,11 +235,6 @@
"internalType": "address", "internalType": "address",
"name": "a", "name": "a",
"type": "address" "type": "address"
},
{
"internalType": "address",
"name": "b",
"type": "address"
} }
], ],
"name": "setPayeeAddress", "name": "setPayeeAddress",
@ -339,19 +255,6 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
}, },
{
"inputs": [
{
"internalType": "address",
"name": "addr",
"type": "address"
}
],
"name": "setTokenIndex",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{ {
"inputs": [ "inputs": [
{ {
@ -365,51 +268,6 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
}, },
{
"inputs": [
{
"internalType": "string",
"name": "source",
"type": "string"
}
],
"name": "stringToBytes32",
"outputs": [
{
"internalType": "bytes32",
"name": "result",
"type": "bytes32"
}
],
"stateMutability": "pure",
"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": [ "inputs": [
{ {
@ -441,6 +299,135 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
}, },
{
"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": [],
"name": "withdraw",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "EquityNFT",
"outputs": [
{
"internalType": "contract RedDevilEquityNFT",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "orderId",
"type": "uint256"
}
],
"name": "getOrderStatus",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"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": "price",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"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": [], "inputs": [],
"name": "usdc", "name": "usdc",

View File

@ -1,10 +1,101 @@
[ [
{
"inputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"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": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{ {
"constant": true, "constant": true,
"inputs": [], "inputs": [],
"name": "name", "name": "_decimals",
"outputs": [ "outputs": [
{ {
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "_name",
"outputs": [
{
"internalType": "string",
"name": "", "name": "",
"type": "string" "type": "string"
} }
@ -13,21 +104,65 @@
"stateMutability": "view", "stateMutability": "view",
"type": "function" "type": "function"
}, },
{
"constant": true,
"inputs": [],
"name": "_symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{ {
"constant": false, "constant": false,
"inputs": [ "inputs": [
{ {
"name": "_spender", "internalType": "address",
"name": "spender",
"type": "address" "type": "address"
}, },
{ {
"name": "_value", "internalType": "uint256",
"name": "amount",
"type": "uint256" "type": "uint256"
} }
], ],
"name": "approve", "name": "approve",
"outputs": [ "outputs": [
{ {
"internalType": "bool",
"name": "", "name": "",
"type": "bool" "type": "bool"
} }
@ -38,10 +173,17 @@
}, },
{ {
"constant": true, "constant": true,
"inputs": [], "inputs": [
"name": "totalSupply", {
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [ "outputs": [
{ {
"internalType": "uint256",
"name": "", "name": "",
"type": "uint256" "type": "uint256"
} }
@ -54,21 +196,15 @@
"constant": false, "constant": false,
"inputs": [ "inputs": [
{ {
"name": "_from", "internalType": "uint256",
"type": "address" "name": "amount",
},
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256" "type": "uint256"
} }
], ],
"name": "transferFrom", "name": "burn",
"outputs": [ "outputs": [
{ {
"internalType": "bool",
"name": "", "name": "",
"type": "bool" "type": "bool"
} }
@ -83,6 +219,7 @@
"name": "decimals", "name": "decimals",
"outputs": [ "outputs": [
{ {
"internalType": "uint8",
"name": "", "name": "",
"type": "uint8" "type": "uint8"
} }
@ -91,54 +228,24 @@
"stateMutability": "view", "stateMutability": "view",
"type": "function" "type": "function"
}, },
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "balance",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{ {
"constant": false, "constant": false,
"inputs": [ "inputs": [
{ {
"name": "_to", "internalType": "address",
"name": "spender",
"type": "address" "type": "address"
}, },
{ {
"name": "_value", "internalType": "uint256",
"name": "subtractedValue",
"type": "uint256" "type": "uint256"
} }
], ],
"name": "transfer", "name": "decreaseAllowance",
"outputs": [ "outputs": [
{ {
"internalType": "bool",
"name": "", "name": "",
"type": "bool" "type": "bool"
} }
@ -149,19 +256,127 @@
}, },
{ {
"constant": true, "constant": true,
"inputs": [ "inputs": [],
"name": "getOwner",
"outputs": [
{ {
"name": "_owner", "internalType": "address",
"type": "address" "name": "",
},
{
"name": "_spender",
"type": "address" "type": "address"
} }
], ],
"name": "allowance", "payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "addedValue",
"type": "uint256"
}
],
"name": "increaseAllowance",
"outputs": [ "outputs": [
{ {
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "mint",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "", "name": "",
"type": "uint256" "type": "uint256"
} }
@ -171,52 +386,75 @@
"type": "function" "type": "function"
}, },
{ {
"payable": true, "constant": false,
"stateMutability": "payable",
"type": "fallback"
},
{
"anonymous": false,
"inputs": [ "inputs": [
{ {
"indexed": true, "internalType": "address",
"name": "owner", "name": "recipient",
"type": "address" "type": "address"
}, },
{ {
"indexed": true, "internalType": "uint256",
"name": "spender", "name": "amount",
"type": "address"
},
{
"indexed": false,
"name": "value",
"type": "uint256" "type": "uint256"
} }
], ],
"name": "Approval", "name": "transfer",
"type": "event" "outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}, },
{ {
"anonymous": false, "constant": false,
"inputs": [ "inputs": [
{ {
"indexed": true, "internalType": "address",
"name": "from", "name": "sender",
"type": "address" "type": "address"
}, },
{ {
"indexed": true, "internalType": "address",
"name": "to", "name": "recipient",
"type": "address" "type": "address"
}, },
{ {
"indexed": false, "internalType": "uint256",
"name": "value", "name": "amount",
"type": "uint256" "type": "uint256"
} }
], ],
"name": "Transfer", "name": "transferFrom",
"type": "event" "outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
} }
] ]

View File

@ -0,0 +1,192 @@
[
{
"inputs": [
{
"internalType": "address",
"name": "payAddr",
"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": "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"
},
{
"inputs": [],
"name": "R_MAB",
"outputs": [
{
"internalType": "contract IERC20",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "orderId",
"type": "uint256"
}
],
"name": "getOrderStatus",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"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": "setUSDCAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "withdraw",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]

View File

@ -1,7 +1,7 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-06-19 15:48:57 * @Date: 2024-06-19 15:48:57
* @LastEditTime: 2024-06-24 18:25:44 * @LastEditTime: 2024-07-19 14:09:28
* @Author: John * @Author: John
*/ */
import { config } from "@/components/WalletProvider"; import { config } from "@/components/WalletProvider";
@ -16,8 +16,10 @@ import { encodeFunctionData } from "viem/utils";
import erc20Abi from "@/contract/abi/erc20abi.json"; import erc20Abi from "@/contract/abi/erc20abi.json";
import usdtAbi from "@/contract/abi/USDT.json"; import usdtAbi from "@/contract/abi/USDT.json";
import RedDevilsAbi from "@/contract/abi/RedDevils.json"; import RedDevilsAbi from "@/contract/abi/RedDevils.json";
import receiveAbi from "@/contract/abi/receive.json";
import i18next from "i18next"; import i18next from "i18next";
import { BaseError } from "wagmi"; import { BaseError } from "wagmi";
import { UserIncome } from "@/server/module";
/** /**
* @description * @description
@ -165,14 +167,15 @@ export async function payByContract(
if (approvedU < amount) { if (approvedU < amount) {
await authorizedU(amount); await authorizedU(amount);
} }
const NFTURI =
console.log("参数:", amount, orderID, payInduction); "https://gateway.lighthouse.storage/ipfs/bafkreicjdund46333jhrj556kkdsi7bqupyt2qi3lmylmtxcfiw7f2afe4";
console.log("参数:", amount, orderID, payInduction, NFTURI);
estimateGas(config, { estimateGas(config, {
to: import.meta.env.VITE_PURCHASED_CONTRACT_ADDRESS, to: import.meta.env.VITE_PURCHASED_CONTRACT_ADDRESS,
data: encodeFunctionData({ data: encodeFunctionData({
abi: RedDevilsAbi, abi: RedDevilsAbi,
functionName: "buyHMNFT", functionName: "buyEquityNFT",
args: [amount, orderID, payInduction], args: [amount, orderID, payInduction, NFTURI],
}), }),
}) })
.then((gas) => { .then((gas) => {
@ -181,8 +184,8 @@ export async function payByContract(
writeContract(config, { writeContract(config, {
abi: RedDevilsAbi, abi: RedDevilsAbi,
address: import.meta.env.VITE_PURCHASED_CONTRACT_ADDRESS, address: import.meta.env.VITE_PURCHASED_CONTRACT_ADDRESS,
functionName: "buyHMNFT", functionName: "buyEquityNFT",
args: [amount, orderID, payInduction], args: [amount, orderID, payInduction, NFTURI],
gas: gasPrice, gas: gasPrice,
}) })
.then((receipt) => { .then((receipt) => {
@ -190,17 +193,18 @@ export async function payByContract(
reslove(receipt); reslove(receipt);
}) })
.catch((err: BaseError) => { .catch((err: BaseError) => {
console.log("buyHMNFT Transaction err", err); console.log("buyEquityNFT Transaction err", err);
reject(err); reject(err);
}); });
}) })
.catch((err: BaseError) => { .catch((err: BaseError) => {
console.log("buyHMNFT estimateGas err", err); console.log("buyEquityNFT estimateGas err", err);
reject(err); reject(err);
}); });
} catch (err) { } catch (err) {
console.log("pay By Contract catch err", err); console.log("pay By Contract catch err", err);
reject(new BaseError(`${err}`)); if (typeof err == "string") return reject(new BaseError(`${err}`));
return reject(err);
} }
}); });
} }
@ -269,35 +273,79 @@ export async function upGradeByContract(amount: bigint, orderID: string) {
} }
/** /**
* receiveByContract * receiveRMABByContract
* @param amount * @param amount
* @param paymentTime
* @param orderID * @param orderID
* @param hashStr
* @returns * @returns
*/ */
export async function receiveByContract( export async function receiveRMABByContract(
amount: bigint, amount: bigint,
paymentTime: number, paymentTime: number,
orderID: string, orderID: string,
hashStr: string hashStr: string
) { ) {
console.log("pay buy contract params", { amount, orderID }); console.log("pay buy contract params", { amount, orderID });
console.log("NETWORK_USDT:", import.meta.env.VITE_NETWORK_USDT_ADDRESS);
return new Promise<string>(async (reslove, reject) => { return new Promise<string>(async (reslove, reject) => {
try { try {
const balance = await getBalance(); console.log("参数:", amount, paymentTime, orderID, hashStr);
if (balance < amount) { estimateGas(config, {
console.log("用户代币余额不足"); to: import.meta.env.VITE_RECEIVE_RAMB_CONTRACT_ADDRESS,
reject(new BaseError(i18next.t("余额不足"))); data: encodeFunctionData({
return; abi: receiveAbi,
} 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: receiveAbi,
address: import.meta.env.VITE_RECEIVE_RAMB_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 rmab Transaction err", err);
reject(err);
});
})
.catch((err: BaseError) => {
console.log("reward rmab estimateGas err", err);
reject(err);
});
} catch (err) {
reject(new BaseError(`${err}`));
}
});
}
console.log("当前要授权的U:", amount); /**
let approvedU = await getApproveUsdt(); * receiveUSDTByContract
if (approvedU < amount) { * @param amount
await authorizedU(amount); * @param paymentTime
} * @param orderID
* @param hashStr
* @returns
*/
export async function receiveUSDTByContract(
amount: bigint,
paymentTime: number,
orderID: string,
hashStr: string
) {
console.log("pay buy contract params", { amount, orderID });
return new Promise<string>(async (reslove, reject) => {
try {
console.log("参数:", amount, paymentTime, orderID, hashStr); console.log("参数:", amount, paymentTime, orderID, hashStr);
estimateGas(config, { estimateGas(config, {
to: import.meta.env.VITE_PURCHASED_CONTRACT_ADDRESS, to: import.meta.env.VITE_PURCHASED_CONTRACT_ADDRESS,
@ -335,3 +383,26 @@ export async function receiveByContract(
} }
}); });
} }
/**
* receiveByContract
* @param type
* @param amount
* @param paymentTime
* @param orderID
* @param hashStr
* @returns
*/
export async function receiveByContract(
type: UserIncome["coinId"],
amount: bigint,
paymentTime: number,
orderID: string,
hashStr: string
) {
if (type == 1) {
return receiveUSDTByContract(amount, paymentTime, orderID, hashStr);
} else if (type == 2) {
return receiveRMABByContract(amount, paymentTime, orderID, hashStr);
}
}

View File

@ -1,9 +1,9 @@
{ {
"AppName": "红魔", "AppName": "红魔",
"红魔NFT": "红魔NFT", "红魔股权NFT": "红魔股权NFT",
"铸造 NFT": "铸造 NFT", "铸造 NFT": "铸造 NFT",
"级别提升": "级别提升", "级别提升": "级别提升",
"资产记录": "资产记录", "收益记录": "收益记录",
"RMOB记录": "RMOB记录", "RMOB记录": "RMOB记录",
"直推列表": "直推列表", "直推列表": "直推列表",
"返回": "返回", "返回": "返回",
@ -16,10 +16,10 @@
"邀请铸造": "邀请铸造", "邀请铸造": "邀请铸造",
"团队社长": "团队社长", "团队社长": "团队社长",
"邀请空投": "邀请空投", "邀请空投": "邀请空投",
"代币": "代币", "收益": "收益",
"Min结束后按照规则进行空投。": "Min结束后按照规则进行空投。", "Min结束后按照规则进行空投。": "Min结束后按照规则进行空投。",
"铸造 NFT 获得代币空投": "铸造 NFT 获得代币空投", "铸造 NFT 获得代币空投": "铸造 NFT 获得代币空投",
"资产金额 = 已领取 + 待处理": "资产金额 = 已领取 + 待处理", "总收益= 已领取 + 待领取": "总收益= 已领取 + 待领取",
"邀请": "邀请", "邀请": "邀请",
"邀请链接": "邀请链接", "邀请链接": "邀请链接",
"普通会员每邀请铸造一个NFT可获得一份空投福利推荐铸造20个NFT的可升级为会长团队中拥有20位会长可升级为基金会社长邀请越多级别越高福利越多。": "普通会员每邀请铸造一个NFT可获得一份空投福利推荐铸造20个NFT的可升级为会长团队中拥有20位会长可升级为基金会社长邀请越多级别越高福利越多。", "普通会员每邀请铸造一个NFT可获得一份空投福利推荐铸造20个NFT的可升级为会长团队中拥有20位会长可升级为基金会社长邀请越多级别越高福利越多。": "普通会员每邀请铸造一个NFT可获得一份空投福利推荐铸造20个NFT的可升级为会长团队中拥有20位会长可升级为基金会社长邀请越多级别越高福利越多。",
@ -42,7 +42,7 @@
"提升级别": "提升级别", "提升级别": "提升级别",
"社长": "社长", "社长": "社长",
"当前升级价格:": "当前升级价格:", "当前升级价格:": "当前升级价格:",
"升级费用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 USDT起50%进入资金池另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始每升级一名社长所需铸造费用增加xxx既第二位社长升级铸造费用为xxxu+xxx*xxx=xxx USDT以此类推。": "升级费用{{value1}} USDT起50%进入资金池另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始,每升级一名社长所需铸造费用增加{{value2}},既第二位社长升级铸造费用为{{value1}}u+{{value1}}*{{value2}}={{value3}} USDT以此类推。",
"升级条件": "升级条件", "升级条件": "升级条件",
"普通会员": "普通会员", "普通会员": "普通会员",
"(限量xxx个)": "(限量 {{value}} 个)", "(限量xxx个)": "(限量 {{value}} 个)",
@ -101,5 +101,13 @@
"正在获取已授权金额": "正在获取已授权金额", "正在获取已授权金额": "正在获取已授权金额",
"升级成功,返回首页查看": "升级成功,返回首页查看", "升级成功,返回首页查看": "升级成功,返回首页查看",
"无级别提升": "无级别提升", "无级别提升": "无级别提升",
"没有更多数据了": "没有更多数据了" "没有更多数据了": "没有更多数据了",
"升级中": "升级中",
"无等级": "无等级",
"无效的邀请链接": "无效的邀请链接",
"交易红魔股权NFT": "交易红魔股权NFT",
"上级链接": "上级链接",
"邀请链接:": "邀请链接:",
"上级地址:": "上级地址:"
} }

View File

@ -1,9 +1,9 @@
{ {
"AppName": "Der Rote Teufel", "AppName": "Der Rote Teufel",
"红魔NFT": "Der Rote Teufel NFT", "红魔股权NFT": "Red Devils Equity NFT",
"铸造 NFT": "NFT Prägen", "铸造 NFT": "NFT Prägen",
"级别提升": "Stufenaufstieg", "级别提升": "Stufenaufstieg",
"资产记录": "Vermögensaufzeichnung", "收益记录": "Ergebnisrekord",
"RMOB记录": "RMOB Aufzeichnung", "RMOB记录": "RMOB Aufzeichnung",
"直推列表": "Direktempfehlungsliste", "直推列表": "Direktempfehlungsliste",
"返回": "Zurück", "返回": "Zurück",
@ -16,10 +16,10 @@
"邀请铸造": "Prägen einladen", "邀请铸造": "Prägen einladen",
"团队社长": "Teamleiter", "团队社长": "Teamleiter",
"邀请空投": "Airdrop einladen", "邀请空投": "Airdrop einladen",
"代币": "Token", "收益": "Einkommen",
"Min结束后按照规则进行空投。": "Airdrop nach dem Ende des Min gemäß den Regeln.", "Min结束后按照规则进行空投。": "Airdrop nach dem Ende des Min gemäß den Regeln.",
"铸造 NFT 获得代币空投": "Token-Airdrop durch NFT-Prägung erhalten", "铸造 NFT 获得代币空投": "Token-Airdrop durch NFT-Prägung erhalten",
"资产金额 = 已领取 + 待处理": "Vermögenswert = Empfang + Ausstehend", "总收益= 已领取 + 待领取": "Gesamtumsatz = Empfang + Abzuholen",
"邀请": "Einladen", "邀请": "Einladen",
"邀请链接": "Einladungslink", "邀请链接": "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.", "普通会员每邀请铸造一个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.",
@ -42,7 +42,7 @@
"提升级别": "Levelaufstieg", "提升级别": "Levelaufstieg",
"社长": "Vorsitzender", "社长": "Vorsitzender",
"当前升级价格:": "Aktueller Upgrade-Preis:", "当前升级价格:": "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.", "升级费用xxx USDT起50%进入资金池另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始每升级一名社长所需铸造费用增加xxx既第二位社长升级铸造费用为xxxu+xxx*xxx=xxx USDT以此类推。": "Upgrade-Kosten ab {{value1}} USDT, 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", "升级条件": "Upgrade-Bedingungen",
"普通会员": "Normales Mitglied", "普通会员": "Normales Mitglied",
"(限量xxx个)": "(Begrenzt auf {{value}} Stück)", "(限量xxx个)": "(Begrenzt auf {{value}} Stück)",
@ -101,5 +101,12 @@
"正在获取已授权金额": "Aktuell wird der autorisierte Betrag abgerufen.", "正在获取已授权金额": "Aktuell wird der autorisierte Betrag abgerufen.",
"升级成功,返回首页查看": "Upgrade erfolgreich abgeschlossen, zurück zur Startseite zur Ansicht.", "升级成功,返回首页查看": "Upgrade erfolgreich abgeschlossen, zurück zur Startseite zur Ansicht.",
"无级别提升": "Beförderung ohne Rang", "无级别提升": "Beförderung ohne Rang",
"没有更多数据了": "Keine weiteren Daten" "没有更多数据了": "Keine weiteren Daten",
"升级中": "Wird aktualisiert",
"无等级": "Keine Bewertung",
"无效的邀请链接": "Ungültiger Einladungslink",
"交易红魔股权NFT": "Handel mit Red Devil Equity NFT",
"上级链接": "Link des Vorgesetzten",
"邀请链接:": "Einladungslink:",
"上级地址:": "Adresse des Vorgesetzten:"
} }

View File

@ -1,9 +1,9 @@
{ {
"AppName": "Red Devils", "AppName": "Red Devils",
"红魔NFT": "Red Devils NFT", "红魔股权NFT": "Red Devil Equity NFT",
"铸造 NFT": "Mint NFT", "铸造 NFT": "Mint NFT",
"级别提升": "Level Up", "级别提升": "Level Up",
"资产记录": "Asset Records", "收益记录": "Revenue Record",
"RMOB记录": "RMOB Records", "RMOB记录": "RMOB Records",
"直推列表": "Direct Referral List", "直推列表": "Direct Referral List",
"返回": "Back", "返回": "Back",
@ -16,10 +16,10 @@
"邀请铸造": "Invite to Mint", "邀请铸造": "Invite to Mint",
"团队社长": "Team Leader", "团队社长": "Team Leader",
"邀请空投": "Invite Airdrop", "邀请空投": "Invite Airdrop",
"代币": "Token", "收益": "Income",
"Min结束后按照规则进行空投。": "Airdrop will follow the rules after Min ends.", "Min结束后按照规则进行空投。": "Airdrop will follow the rules after Min ends.",
"铸造 NFT 获得代币空投": "Mint NFT for Token Airdrop", "铸造 NFT 获得代币空投": "Mint NFT for Token Airdrop",
"资产金额 = 已领取 + 待处理": "Asset Amount = Claimed + Pending", "总收益= 已领取 + 待领取": "Total Revenue = Claimed + Pending",
"邀请": "Invite", "邀请": "Invite",
"邀请链接": "Invite Link", "邀请链接": "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.", "普通会员每邀请铸造一个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.",
@ -36,13 +36,13 @@
"当前MINT价格": "Current MINT Price:", "当前MINT价格": "Current MINT Price:",
"价格说明:": "Price Explanation:", "价格说明:": "Price Explanation:",
"{{value1}} USDT起每增加 {{value2}} 名普通会员NFT价格上涨 {{value3}},既:前 {{value2}} 名价格为 {{value1}} USDT/枚value4 名价格为{{value1}}u+{{value1}}u*{{value3}}={{value5}} USDT/枚,以此类推。": "Starting at {{value1}} USDT, the NFT price increases by {{value3}} for every {{value2}} new members: first {{value2}} at {{value1}} USDT each, {{value4}} at {{value1}}u+{{value1}}u*{{value3}}={{value5}} USDT each, and so on.", "{{value1}} USDT起每增加 {{value2}} 名普通会员NFT价格上涨 {{value3}},既:前 {{value2}} 名价格为 {{value1}} USDT/枚value4 名价格为{{value1}}u+{{value1}}u*{{value3}}={{value5}} USDT/枚,以此类推。": "Starting at {{value1}} USDT, the NFT price increases by {{value3}} for every {{value2}} new members: first {{value2}} at {{value1}} USDT each, {{value4}} at {{value1}}u+{{value1}}u*{{value3}}={{value5}} USDT each, and so on.",
"授权USDT": "Authorize USDT", "授权USDT": "Approve USDT",
"当前级别": "Current Level", "当前级别": "Current Level",
"普通活跃": "Active Member", "普通活跃": "Active Member",
"提升级别": "Upgrade Level", "提升级别": "Upgrade Level",
"社长": "Leader", "社长": "Leader",
"当前升级价格:": "Current Upgrade Price:", "当前升级价格:": "Current Upgrade Price:",
"升级费用xxx USDT起其中gas费2USDT剩余部分50%进入资金池另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始每升级一名社长所需铸造费用增加xxx既第二位社长升级铸造费用为xxxu+xxx*xxx=xxx USDT以此类推。": "Upgrade cost starts at {{value1}} USDT, including 2USDT gas fee; 50% goes to the fund pool, and 50% is distributed among successful Leaders and Foundation Leaders. From the second Leader onwards, each upgrade cost increases by {{value2}}, i.e., second Leader upgrade costs {{value1}}u+{{value1}}*{{value2}}={{value3}} USDT, and so on.", "升级费用xxx USDT起50%进入资金池另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始每升级一名社长所需铸造费用增加xxx既第二位社长升级铸造费用为xxxu+xxx*xxx=xxx USDT以此类推。": "Upgrade cost starts at {{value1}} USDT, 50% goes to the fund pool, and 50% is distributed among successful Leaders and Foundation Leaders. From the second Leader onwards, each upgrade cost increases by {{value2}}, i.e., second Leader upgrade costs {{value1}}u+{{value1}}*{{value2}}={{value3}} USDT, and so on.",
"升级条件": "Upgrade Conditions", "升级条件": "Upgrade Conditions",
"普通会员": "Regular Member", "普通会员": "Regular Member",
"(限量xxx个)": "(Limited to {{value}})", "(限量xxx个)": "(Limited to {{value}})",
@ -96,10 +96,17 @@
"正在授权USDT": "Authorizing USDT", "正在授权USDT": "Authorizing USDT",
"购买中": "Purchasing", "购买中": "Purchasing",
"领取中": "Processing", "领取中": "Processing",
"MINT Nft 获取邀请链接": "MINT Nft invite link", "MINT Nft 获取邀请链接": "Mint NFT to get invitation link",
"链接钱包获取邀请链接": "Link your wallet to get the invitation link.", "链接钱包获取邀请链接": "Link your wallet to get the invitation link.",
"正在获取已授权金额": "Currently retrieving authorized amount.", "正在获取已授权金额": "Currently retrieving authorized amount.",
"升级成功,返回首页查看": "Upgrade successful, return to homepage to view.", "升级成功,返回首页查看": "Upgrade successful, return to homepage to view.",
"无级别提升": "Promotion without rank", "无级别提升": "Promotion without rank",
"没有更多数据了": "No more data" "没有更多数据了": "No more data",
"升级中": "Upgrading",
"无等级": "No Grade",
"无效的邀请链接": "Invalid invitation link",
"交易红魔股权NFT": "Trade Red Devil Equity NFT",
"上级链接": "Superior's Link",
"邀请链接:": "Invitation Link:",
"上级地址:": "Superior's Address:"
} }

View File

@ -1,9 +1,9 @@
{ {
"AppName": "紅魔", "AppName": "紅魔",
"红魔NFT": "紅魔NFT", "红魔股权NFT": "レッドデビルズ株式NFT",
"铸造 NFT": "NFT 鋳造", "铸造 NFT": "NFT 鋳造",
"级别提升": "レベルアップ", "级别提升": "レベルアップ",
"资产记录": "資産記録", "收益记录": "収益実績",
"RMOB记录": "RMOB記録", "RMOB记录": "RMOB記録",
"直推列表": "ダイレクト推薦リスト", "直推列表": "ダイレクト推薦リスト",
"返回": "戻る", "返回": "戻る",
@ -16,10 +16,10 @@
"邀请铸造": "鋳造を招待", "邀请铸造": "鋳造を招待",
"团队社长": "チームリーダー", "团队社长": "チームリーダー",
"邀请空投": "エアドロップ招待", "邀请空投": "エアドロップ招待",
"代币": "トークン", "收益": "所得",
"Min结束后按照规则进行空投。": "Min終了後、ルールに従ってエアドロップを行います。", "Min结束后按照规则进行空投。": "Min終了後、ルールに従ってエアドロップを行います。",
"铸造 NFT 获得代币空投": "NFTを鋳造してトークンエアドロップを獲得", "铸造 NFT 获得代币空投": "NFTを鋳造してトークンエアドロップを獲得",
"资产金额 = 已领取 + 待处理": "資産額 = 受領済み + 処理中", "总收益= 已领取 + 待领取": "総収入 = 受領済み + 回収対象",
"邀请": "招待", "邀请": "招待",
"邀请链接": "招待リンク", "邀请链接": "招待リンク",
"普通会员每邀请铸造一个NFT可获得一份空投福利推荐铸造20个NFT的可升级为会长团队中拥有20位会长可升级为基金会社长邀请越多级别越高福利越多。": "一般会員はNFT鋳造の招待ごとにエアドロップを獲得20個のNFTを鋳造することでリーダーに昇格チーム内に20人のリーダーがいるとファンドリーダーに昇格招待が多いほどレベルが上がり、特典が増える。", "普通会员每邀请铸造一个NFT可获得一份空投福利推荐铸造20个NFT的可升级为会长团队中拥有20位会长可升级为基金会社长邀请越多级别越高福利越多。": "一般会員はNFT鋳造の招待ごとにエアドロップを獲得20個のNFTを鋳造することでリーダーに昇格チーム内に20人のリーダーがいるとファンドリーダーに昇格招待が多いほどレベルが上がり、特典が増える。",
@ -42,7 +42,7 @@
"提升级别": "レベルアップ", "提升级别": "レベルアップ",
"社长": "リーダー", "社长": "リーダー",
"当前升级价格:": "現在のアップグレード価格:", "当前升级价格:": "現在のアップグレード価格:",
"升级费用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 USDT起50%进入资金池另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始每升级一名社长所需铸造费用增加xxx既第二位社长升级铸造费用为xxxu+xxx*xxx=xxx USDT以此类推。": "アップグレード費用は{{value1}} USDTから、残りの50%は資金プールに入り、もう50%はアップグレードに成功したリーダーとファンドリーダーに分配。2人目のリーダーからは、アップグレード費用が{{value2}}ずつ増加、つまり2人目は{{value1}}u+{{value1}}*{{value2}}={{value3}} USDT、以降も同様。",
"升级条件": "アップグレード条件", "升级条件": "アップグレード条件",
"普通会员": "一般会員", "普通会员": "一般会員",
"(限量xxx个)": "(限定 {{value}} 個)", "(限量xxx个)": "(限定 {{value}} 個)",
@ -101,5 +101,13 @@
"正在获取已授权金额": "承認済み金額を取得中です", "正在获取已授权金额": "承認済み金額を取得中です",
"升级成功,返回首页查看": "アップグレードが成功しました。ホームページに戻って確認してください。", "升级成功,返回首页查看": "アップグレードが成功しました。ホームページに戻って確認してください。",
"无级别提升": "階級なしの昇進", "无级别提升": "階級なしの昇進",
"没有更多数据了": "これ以上のデータはありません" "没有更多数据了": "これ以上のデータはありません",
"升级中": "アップグレード中",
"无等级": "グレードなし",
"无效的邀请链接": "無効な招待リンクです",
"交易红魔股权NFT": "レッドデビル株式NFTを取引する",
"上级链接": "上司のリンク",
"邀请链接:": "招待リンク:",
"上级地址:": "上司の住所:"
} }

View File

@ -1,9 +1,9 @@
{ {
"AppName": "紅魔", "AppName": "紅魔",
"红魔NFT": "紅魔NFT", "红魔股权NFT": "紅魔鬼股權NFT",
"铸造 NFT": "鑄造 NFT", "铸造 NFT": "鑄造 NFT",
"级别提升": "級別提升", "级别提升": "級別提升",
"资产记录": "資產記錄", "收益记录": "收益記錄",
"RMOB记录": "RMOB記錄", "RMOB记录": "RMOB記錄",
"直推列表": "直推列表", "直推列表": "直推列表",
"返回": "返回", "返回": "返回",
@ -16,10 +16,10 @@
"邀请铸造": "邀請鑄造", "邀请铸造": "邀請鑄造",
"团队社长": "團隊社長", "团队社长": "團隊社長",
"邀请空投": "邀請空投", "邀请空投": "邀請空投",
"代币": "代幣", "收益": "收益",
"Min结束后按照规则进行空投。": "Min結束後按照規則進行空投。", "Min结束后按照规则进行空投。": "Min結束後按照規則進行空投。",
"铸造 NFT 获得代币空投": "鑄造 NFT 獲得代幣空投", "铸造 NFT 获得代币空投": "鑄造 NFT 獲得代幣空投",
"资产金额 = 已领取 + 待处理": "資產金額 = 已領取 + 待處理", "总收益= 已领取 + 待领取": "總收益 = 已領取 + 待領取",
"邀请": "邀請", "邀请": "邀請",
"邀请链接": "邀請鏈接", "邀请链接": "邀請鏈接",
"普通会员每邀请铸造一个NFT可获得一份空投福利推荐铸造20个NFT的可升级为会长团队中拥有20位会长可升级为基金会社长邀请越多级别越高福利越多。": "普通會員每邀請鑄造一個NFT可獲得一份空投福利推薦鑄造20個NFT的可升級為會長團隊中擁有20位會長可升級為基金會社長邀請越多級別越高福利越多。", "普通会员每邀请铸造一个NFT可获得一份空投福利推荐铸造20个NFT的可升级为会长团队中拥有20位会长可升级为基金会社长邀请越多级别越高福利越多。": "普通會員每邀請鑄造一個NFT可獲得一份空投福利推薦鑄造20個NFT的可升級為會長團隊中擁有20位會長可升級為基金會社長邀請越多級別越高福利越多。",
@ -42,7 +42,7 @@
"提升级别": "提升級別", "提升级别": "提升級別",
"社长": "社長", "社长": "社長",
"当前升级价格:": "當前升級價格:", "当前升级价格:": "當前升級價格:",
"升级费用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 USDT起50%进入资金池另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始每升级一名社长所需铸造费用增加xxx既第二位社长升级铸造费用为xxxu+xxx*xxx=xxx USDT以此类推。": "升級費用{{value1}} USDT起50%進入資金池另外50%平均分給所有升級成功的社長和基金會社長。自第二個社長升級開始,每升級一名社長所需鑄造費用增加{{value2}},即第二位社長升級鑄造費用為{{value1}}u+{{value1}}*{{value2}}={{value3}} USDT以此類推。",
"升级条件": "升級條件", "升级条件": "升級條件",
"普通会员": "普通會員", "普通会员": "普通會員",
"(限量xxx个)": "(限量 {{value}} 個)", "(限量xxx个)": "(限量 {{value}} 個)",
@ -101,5 +101,13 @@
"正在获取已授权金额": "正在取得已授權金額", "正在获取已授权金额": "正在取得已授權金額",
"升级成功,返回首页查看": "升級成功,返回首頁查看。", "升级成功,返回首页查看": "升級成功,返回首頁查看。",
"无级别提升": "無級別提升", "无级别提升": "無級別提升",
"没有更多数据了": "沒有更多數據了" "没有更多数据了": "沒有更多數據了",
"升级中": "升級中",
"无等级": "無等級",
"无效的邀请链接": "無效的邀請連結",
"交易红魔股权NFT": "交易紅魔股權NFT",
"上级链接": "上級鏈接",
"邀请链接:": "邀請鏈接:",
"上级地址:": "上級地址:"
} }

View File

@ -1,7 +1,7 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-06-17 17:20:03 * @Date: 2024-06-17 17:20:03
* @LastEditTime: 2024-06-20 11:43:14 * @LastEditTime: 2024-07-02 11:38:25
* @Author: John * @Author: John
*/ */
import "@/i18n/init.ts"; import "@/i18n/init.ts";
@ -15,9 +15,9 @@ import EventBusProvider from "./context/EventBusContext.tsx";
import { WalletProvider } from "./components/WalletProvider.tsx"; import { WalletProvider } from "./components/WalletProvider.tsx";
import flexible from "./utils/flexible.ts"; import flexible from "./utils/flexible.ts";
import VConsole from "vconsole"; import VConsole from "vconsole";
import { getUrlQueryParam } from "./utils/index.ts"; import { getUrlParameterByName } from "./utils/index.ts";
if (getUrlQueryParam("vconsole") === "1") { if (getUrlParameterByName("vconsole") === "1") {
new VConsole(); new VConsole();
} }
flexible(window, document); flexible(window, document);

View File

@ -1,12 +1,12 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-06-18 17:57:13 * @Date: 2024-06-18 17:57:13
* @LastEditTime: 2024-06-24 10:44:10 * @LastEditTime: 2024-07-02 17:43:52
* @Author: John * @Author: John
*/ */
import Tabs from "antd-mobile/es/components/tabs"; import Tabs from "antd-mobile/es/components/tabs";
import classes from "./AssetRecord.module.css"; import classes from "./AssetRecord.module.css";
import { cn, getUrlQueryParam } from "@/utils"; import { cn, getUrlParameterByName } from "@/utils";
import CapsuleTabs from "antd-mobile/es/components/capsule-tabs"; import CapsuleTabs from "antd-mobile/es/components/capsule-tabs";
import RecordsItem from "@/components/RecordsItem"; import RecordsItem from "@/components/RecordsItem";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@ -14,13 +14,12 @@ import { useEffect, useMemo, useRef, useState } from "react";
import { api_pagling_query_income_record } from "@/server/api"; import { api_pagling_query_income_record } from "@/server/api";
import { IncomeRecord, IncomeRecordType } from "@/server/module"; import { IncomeRecord, IncomeRecordType } from "@/server/module";
import { Empty, InfiniteScroll } from "antd-mobile"; import { Empty, InfiniteScroll } from "antd-mobile";
import { CoinName } from "@/constants";
export default function () { export default function () {
const { t } = useTranslation(); const { t } = useTranslation();
const coinId = useMemo(() => getUrlQueryParam("id"), []); const id = useMemo(() => getUrlParameterByName("id"), []);
const coinName = useMemo(() => getUrlQueryParam("name"), []); const coinId = useMemo(() => getUrlParameterByName("coinId"), []);
const currentType = useRef<1 | 2>(1); const currentType = useRef<1 | 2>(2);
const [issueRecords, setIssueRecords] = useState<IncomeRecord["records"]>([]); const [issueRecords, setIssueRecords] = useState<IncomeRecord["records"]>([]);
const [receiveRecord, setReceiveRecord] = useState<IncomeRecord["records"]>( const [receiveRecord, setReceiveRecord] = useState<IncomeRecord["records"]>(
[] []
@ -31,11 +30,11 @@ export default function () {
const hasMore = useRef<boolean>(true); const hasMore = useRef<boolean>(true);
useEffect(() => { useEffect(() => {
return () => {}; return () => {};
}, [coinId]); }, []);
async function getRecord() { async function getRecord() {
return new Promise<void>(async (reslove) => { return new Promise<void>(async (reslove) => {
if (!coinId) return; if (!id) return;
if (!hasMore.current) return; if (!hasMore.current) return;
@ -43,11 +42,11 @@ export default function () {
pageNum.current++; pageNum.current++;
const { data } = await api_pagling_query_income_record().send({ const { data } = await api_pagling_query_income_record().send({
queryParams: { queryParams: {
id: coinId, id,
type: currentType.current, type: currentType.current,
pageNum: pageNum.current, pageNum: pageNum.current,
pageSize, pageSize,
...(conditions.current && currentType.current == 1 ...(conditions.current && currentType.current == 2
? { status: conditions.current } ? { status: conditions.current }
: {}), : {}),
}, },
@ -57,7 +56,7 @@ export default function () {
if (data.data.records.length < pageSize) hasMore.current = false; if (data.data.records.length < pageSize) hasMore.current = false;
if (currentType.current == 1) { if (currentType.current == 2) {
setIssueRecords([...issueRecords, ...data?.data.records]); setIssueRecords([...issueRecords, ...data?.data.records]);
} else { } else {
setReceiveRecord([...receiveRecord, ...data?.data.records]); setReceiveRecord([...receiveRecord, ...data?.data.records]);
@ -67,9 +66,9 @@ export default function () {
} }
function resetPaging() { function resetPaging() {
if (currentType.current == 1) { if (currentType.current == 2) {
setIssueRecords([]); setIssueRecords([]);
} else if (currentType.current == 2) { } else if (currentType.current == 1) {
setReceiveRecord([]); setReceiveRecord([]);
} }
pageNum.current = 0; pageNum.current = 0;
@ -82,16 +81,16 @@ export default function () {
className={cn(classes.AssetRecord)} className={cn(classes.AssetRecord)}
onChange={(key) => { onChange={(key) => {
if (parseInt(key) == 1) { if (parseInt(key) == 1) {
currentType.current = 1; currentType.current = 2;
resetPaging(); resetPaging();
} else { } else {
currentType.current = 2; currentType.current = 1;
resetPaging(); resetPaging();
} }
}} }}
> >
<Tabs.Tab className={classes.tab} title={t("发放记录")} key="1"> <Tabs.Tab className={classes.tab} title={t("发放记录")} key="1">
{coinName == CoinName.USDT && ( {coinId == "1" && (
<CapsuleTabs <CapsuleTabs
onChange={(key) => { onChange={(key) => {
switch (key) { switch (key) {
@ -117,7 +116,7 @@ export default function () {
</CapsuleTabs> </CapsuleTabs>
)} )}
{coinName == CoinName.RMOB && ( {coinId == "2" && (
<CapsuleTabs <CapsuleTabs
onChange={(key) => { onChange={(key) => {
switch (key) { switch (key) {

View File

@ -204,7 +204,7 @@
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
li { li {
width: 76px; min-width: 76px;
height: 34px; height: 34px;
opacity: 1; opacity: 1;
@ -220,6 +220,7 @@
color: #4d4d4d; color: #4d4d4d;
text-align: center; text-align: center;
line-height: 34px; line-height: 34px;
padding: 0 10px;
&.nftToken_tab_active { &.nftToken_tab_active {
border-radius: 10px; border-radius: 10px;
opacity: 1; opacity: 1;
@ -585,6 +586,43 @@
} }
} }
.equityNft {
display: flex;
flex-direction: row;
align-items: center;
gap: 16px;
padding: 10px 15px;
border-radius: 14px;
opacity: 1;
background: #171719;
margin-top: 26px;
> svg {
width: 26px;
height: 26px;
&:nth-of-type(2) {
margin-left: auto;
}
}
span {
opacity: 1;
font-family: DM Sans;
font-size: 14px;
font-weight: 500;
line-height: normal;
letter-spacing: 0em;
font-variation-settings: "opsz" auto;
font-feature-settings: "kern" on;
color: #ffffff;
z-index: 1;
}
}
.invite { .invite {
margin-top: 25px; margin-top: 25px;
.invite_top { .invite_top {
@ -647,7 +685,8 @@
margin-top: 10px; margin-top: 10px;
> span { > span {
&:nth-of-type(1) { &:nth-of-type(1),
&:nth-of-type(3) {
/* 自动布局子元素 */ /* 自动布局子元素 */
opacity: 0.8; opacity: 0.8;
@ -663,6 +702,9 @@
z-index: 0; z-index: 0;
} }
&:nth-of-type(3) {
margin-top: 20px;
}
&:nth-of-type(2) { &:nth-of-type(2) {
/* 自动布局子元素 */ /* 自动布局子元素 */
@ -708,11 +750,38 @@
gap: 16px; gap: 16px;
white-space: nowrap; white-space: nowrap;
}
}
.superior_content_link {
display: flex;
align-items: center;
gap: 10px;
.invite_content_icon { > span {
width: 24px; /* 自动布局子元素 */
height: 24px; opacity: 1;
}
font-family: DM Sans;
font-size: 14px;
font-weight: 500;
line-height: normal;
letter-spacing: 0em;
font-variation-settings: "opsz" auto;
font-feature-settings: "kern" on;
color: #ffffff;
z-index: 0;
display: flex;
align-items: center;
gap: 16px;
white-space: nowrap;
}
.invite_content_icon {
margin-left: auto;
} }
} }
} }

View File

@ -1,6 +1,6 @@
import classes from "./Home.module.css"; import classes from "./Home.module.css";
import useUserStore from "@/store/User"; import useUserStore from "@/store/User";
import { cn, copyText, shortenString } from "@/utils"; import { cn, copyText, padWithZero, shortenString } from "@/utils";
import { useWeb3Modal } from "@web3modal/wagmi/react"; import { useWeb3Modal } from "@web3modal/wagmi/react";
import { useEffect, useMemo, useRef, useState } from "react"; import { useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@ -10,18 +10,20 @@ import usdtBg from "@/assets/usdt_bg.svg";
import RMOB_logo from "@/assets/RMOB_logo.svg"; import RMOB_logo from "@/assets/RMOB_logo.svg";
import IconFont from "@/components/iconfont"; import IconFont from "@/components/iconfont";
import { BaseError, useAccount } from "wagmi"; import { BaseError, useAccount } from "wagmi";
import { disconnect } from "wagmi/actions";
import { config } from "@/components/WalletProvider";
import { useNavigate } from "react-router-dom"; import { 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 { loginOut } from "@/utils/wallet";
import { api_claim_income, api_get_homepage_user_data } from "@/server/api"; import {
import { UserHomeData } from "@/server/module"; api_claim_income,
api_get_homepage_user_data,
api_get_user_superiors,
} from "@/server/api";
import { UserHomeData, UserIncome } from "@/server/module";
import { UrlQueryParamsKey } from "@/constants"; import { UrlQueryParamsKey } from "@/constants";
import { receiveByContract } from "@/contract/utils"; import { receiveByContract } from "@/contract/utils";
import usePollingCheckBuyStatus from "@/hook/usePollingCheckBuyStatus"; import usePollingCheckBuyStatus from "@/hook/usePollingCheckBuyStatus";
import { ToastHandler } from "antd-mobile/es/components/toast"; import { ToastHandler } from "antd-mobile/es/components/toast";
import { PullStatus } from "antd-mobile/es/components/pull-to-refresh";
export default function () { export default function () {
const { Token, UpdateToken } = useUserStore(); const { Token, UpdateToken } = useUserStore();
const { open } = useWeb3Modal(); const { open } = useWeb3Modal();
@ -32,26 +34,51 @@ export default function () {
const navigate = useNavigate(); const navigate = useNavigate();
const [userData, setUserData] = useState<UserHomeData>(); const [userData, setUserData] = useState<UserHomeData>();
const [superiorsAddress, setSuperiorsAddress] = useState<string>();
const [superiorsShareCode, setSuperiorsShareCode] = useState<string>();
const statusRecord: Record<PullStatus, string> = {
pulling: "Pull down to refresh",
canRelease: "Release to refresh immediately",
refreshing: "Loading...",
complete: "Refresh complete",
};
const userInviteLink = useMemo( const userInviteLink = useMemo(
() => () =>
`${import.meta.env.VITE_BASE_URL}?${UrlQueryParamsKey.INVITE_CODE}=${ `${location.origin}/#/?${UrlQueryParamsKey.INVITE_CODE}=${
userData?.invitationCode || "" userData?.invitationCode || ""
}`, }`,
[userData] [userData]
); );
const superiorInvitationLink = useMemo(
() =>
`${location.origin}/#/?${UrlQueryParamsKey.INVITE_CODE}=${superiorsShareCode}`,
[superiorsShareCode]
);
const receiveLoadingToast = useRef<ToastHandler>(); const receiveLoadingToast = useRef<ToastHandler>();
const { transcationStatus, startPollingCheckBuyStatus,stopPollingCheckBuyStatus } = const {
usePollingCheckBuyStatus("NORMAL"); transcationStatus,
startPollingCheckBuyStatus,
stopPollingCheckBuyStatus,
} = usePollingCheckBuyStatus("NORMAL");
useEffect(() => { useEffect(() => {
getHomeData(); getHomeData();
if (Token) {
api_get_user_superiors()
.send({})
.then((res) => {
setSuperiorsAddress(res.data?.data.address);
setSuperiorsShareCode(res.data?.data.shareCode);
});
}
return () => {}; return () => {};
}, [Token]); }, [Token]);
useEffect(() => { useEffect(() => {
if (transcationStatus == "success") { if (transcationStatus == "success") {
receiveLoadingToast.current?.close(); receiveLoadingToast.current?.close();
stopPollingCheckBuyStatus() stopPollingCheckBuyStatus();
Dialog.alert({ Dialog.alert({
content: `${t("领取成功,前往钱包查看")}`, content: `${t("领取成功,前往钱包查看")}`,
confirmText: "OK", confirmText: "OK",
@ -74,330 +101,396 @@ export default function () {
return ( return (
<> <>
<div className={cn(classes.Home, classes.container)}> <PullToRefresh
<div className={classes.userinfo}> onRefresh={async () => {
<div className={classes.userinfo_top}> await getHomeData();
<img className={classes.userinfo_top_left} src={logo} alt="" /> }}
renderText={(status) => {
return <div>{statusRecord[status]}</div>;
}}
disabled={!Token}
>
<div className={cn(classes.Home, classes.container)}>
<div className={classes.userinfo}>
<div className={classes.userinfo_top}>
<img
className={classes.userinfo_top_left}
src={userData?.userImg || logo}
alt=""
/>
{address ? ( {address ? (
<div className={classes.userinfo_top_right}> <div className={classes.userinfo_top_right}>
<div className={classes.userinfo_top_right_wallet}> <div className={classes.userinfo_top_right_wallet}>
<span>{shortenString(address, 6, 4)}</span> <span>{shortenString(address, 6, 4)}</span>
<IconFont <IconFont
onClick={async () => {
loginOut();
}}
name="tuichu"
className={classes.userinfo_top_right_wallet_disconnect}
color={"#fff"}
/>
</div>
<div className={classes.userinfo_top_right_btns}>
{userData && (
<>
<div className={classes.userinfo_top_right_btns_item}>
{userData.level == 0 && (
<>
<IconFont
name="tongdun"
className={classes.userinfo_top_right_btns_icon}
/>
<span>{t("无等级")}</span>
</>
)}
{userData.level == 1 && (
<>
<IconFont
name="jindun"
className={classes.userinfo_top_right_btns_icon}
/>
{userData.active === 0 && (
<span>{t("普通非活跃")}</span>
)}
{userData.active === 1 && (
<span>{t("普通活跃")}</span>
)}
</>
)}
{userData.level == 2 && (
<>
<IconFont
name="xingdun"
className={classes.userinfo_top_right_btns_icon}
/>
<span>{t("社长")}</span>
</>
)}
{userData.level == 3 && (
<>
<IconFont
name="guanjun"
className={classes.userinfo_top_right_btns_icon}
/>
<span>{t("基金会社长")}</span>
</>
)}
</div>
<div
className={classes.userinfo_top_right_btns_item}
onClick={() => {
navigate("/levelup");
}}
>
<span>{t("升级")}</span>
<IconFont
name="chevronsrightshuangyoujiantou"
className={classes.userinfo_top_right_btns_icon}
color={"#fff"}
/>
</div>
</>
)}
</div>
</div>
) : (
<>
<div
className={classes.userinfo_top_right_connect}
onClick={() => { onClick={() => {
disconnect(config); open();
loginOut();
}} }}
name="tuichu" >
className={classes.userinfo_top_right_wallet_disconnect} <span>{t("链接钱包")}</span>
color={"#fff"} </div>
/> </>
</div> )}
<div className={classes.userinfo_top_right_btns}> </div>
{userData && ( <ul className={classes.userinfo_data}>
<> <li>
<div className={classes.userinfo_top_right_btns_item}> <span className={classes.userinfo_data_num}>
{userData.level == 0 && ( {userData?.mintNumber || 0}
<> </span>
<IconFont <span className={classes.userinfo_data_des}>
name="tongdun" {t("邀请铸造")}
className={classes.userinfo_top_right_btns_icon} </span>
/> </li>
<span>{t("普通非活跃")}</span> <li>
</> <span className={classes.userinfo_data_num}>
)} {userData?.presidentNumber || 0}
{userData.level == 1 && ( </span>
<> <span className={classes.userinfo_data_des}>
<IconFont {t("团队社长")}
name="jindun" </span>
className={classes.userinfo_top_right_btns_icon} </li>
/> <li>
<span>{t("普通活跃")}</span> <span className={classes.userinfo_data_num}>
</> {userData?.airdropNumber || 0}
)} </span>
{userData.level == 2 && ( <span className={classes.userinfo_data_des}>
<> {t("邀请空投")}
<IconFont </span>
name="xingdun" </li>
className={classes.userinfo_top_right_btns_icon} </ul>
/>
<span>{t("社长")}</span>
</>
)}
{userData.level == 3 && (
<>
<IconFont
name="guanjun"
className={classes.userinfo_top_right_btns_icon}
/>
<span>{t("基金会社长")}</span>
</>
)}
</div>
<div
className={classes.userinfo_top_right_btns_item}
onClick={() => {
navigate("/levelup");
}}
>
<span>{t("升级")}</span>
<IconFont
name="chevronsrightshuangyoujiantou"
className={classes.userinfo_top_right_btns_icon}
color={"#fff"}
/>
</div>
</>
)}
</div>
</div>
) : (
<>
<div
className={classes.userinfo_top_right_connect}
onClick={() => {
open();
}}
>
<span>{t("链接钱包")}</span>
</div>
</>
)}
</div> </div>
<ul className={classes.userinfo_data}>
<li>
<span className={classes.userinfo_data_num}>
{userData?.mintNumber || 0}
</span>
<span className={classes.userinfo_data_des}>{t("邀请铸造")}</span>
</li>
<li>
<span className={classes.userinfo_data_num}>
{userData?.presidentNumber || 0}
</span>
<span className={classes.userinfo_data_des}>{t("团队社长")}</span>
</li>
<li>
<span className={classes.userinfo_data_num}>
{userData?.airdropNumber || 0}
</span>
<span className={classes.userinfo_data_des}>{t("邀请空投")}</span>
</li>
</ul>
</div>
<div className={classes.nftToken}> <div className={classes.nftToken}>
<ul className={classes.nftToken_tab}> <ul className={classes.nftToken_tab}>
<li <li
className={tabIndex == 0 ? classes.nftToken_tab_active : ""} className={tabIndex == 0 ? classes.nftToken_tab_active : ""}
onClick={() => setTabIndex(0)} onClick={() => setTabIndex(0)}
> >
NFT NFT
</li> </li>
<li <li
className={tabIndex == 1 ? classes.nftToken_tab_active : ""} className={tabIndex == 1 ? classes.nftToken_tab_active : ""}
onClick={() => setTabIndex(1)} onClick={() => setTabIndex(1)}
> >
{t("代币")} {t("收益")}
</li> </li>
</ul> </ul>
<div className={classes.nftToken_content}> <div className={classes.nftToken_content}>
{tabIndex == 0 && ( {tabIndex == 0 && (
<> <>
{address ? ( {address ? (
<> <>
{userData?.nftId ? ( {userData?.nftId ? (
<div className={classes.nftToken_content_nft}> <div className={classes.nftToken_content_nft}>
<div className={classes.nftToken_content_nft_top}> <div className={classes.nftToken_content_nft_top}>
<span># ${userData?.nftId}</span> <span># {padWithZero(userData?.nftId)}</span>
<span <span
onClick={() => {
navigate("/mint");
}}
>
{t("铸造 NFT")}
<IconFont
name="chevronsrightshuangyoujiantou"
color={"#F3BE3C"}
/>
</span>
</div>
<img
className={classes.nftToken_content_nft_img}
src={nftBg}
alt=""
/>
<span className={classes.nftToken_content_nft_des}>
{t("Min结束后按照规则进行空投。")}
</span>
</div>
) : (
<div className={classes.nftToken_content_nft_mint}>
<div
className={classes.nftToken_content_nft_mint_btn}
onClick={() => { onClick={() => {
navigate("/mint"); navigate("/mint");
}} }}
> >
{t("铸造 NFT")} <span>{t("铸造 NFT")}</span>
<IconFont <IconFont
className={
classes.nftToken_content_nft_mint_btn_icon
}
name="chevronsrightshuangyoujiantou" name="chevronsrightshuangyoujiantou"
color={"#F3BE3C"} color={"#fff"}
/> />
</span> </div>
<span>{t("铸造 NFT 获得代币空投")}</span>
</div> </div>
<img )}
className={classes.nftToken_content_nft_img} </>
src={nftBg} ) : (
alt="" <>
/> <div className={classes.nftToken_content_userDisconnect}>
<span className={classes.nftToken_content_nft_des}> <span>{t("钱包未链接,无法向您显示 NFT")}</span>
{t("Min结束后按照规则进行空投。")}
</span>
</div> </div>
) : ( </>
<div className={classes.nftToken_content_nft_mint}> )}
<div </>
className={classes.nftToken_content_nft_mint_btn} )}
{tabIndex == 1 && (
<div className={classes.nftToken_content_token}>
<div className={classes.nftToken_content_token_top}>
<span>{t("总收益= 已领取 + 待领取")}</span>
</div>
<ul className={classes.nftToken_content_token_list}>
{userData?.userIncomes.map((v, i) => (
<ReceiveCom
key={i}
coinId={v.coinId}
tokenName={v.coinName}
tokenNum={v.receive}
toReceive={v.collection}
onAssetRec={() => {
navigate(
`/assetrecord?id=${v.id}&coinId=${v.coinId}`
);
}}
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(
v.coinId,
buyAmount,
orderInfo.time,
orderInfo?.orderNumber,
orderInfo.hash
)
.then((hash) => {
if (!hash) return;
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) && <Empty />}
</ul>
</div>
)}
</div>
</div>
<div
className={classes.equityNft}
onClick={() => window.open("https://element.market/account")}
>
<IconFont name="transfer" />
<span>{t("交易红魔股权NFT")}</span>
<IconFont name="chevronsrightshuangyoujiantou" color={"#FFFFFF"} />
</div>
<div className={classes.invite}>
<div className={classes.invite_top}>
<span>{t("邀请")}</span>
{address && (
<span
onClick={() => {
navigate("/invitationlist");
}}
>
{t("邀请列表")}{" "}
<IconFont
name="chevronsrightshuangyoujiantou"
color={"#F3BE3C"}
/>
</span>
)}
</div>
<div className={classes.invite_content}>
<span>{t("邀请链接")}</span>
<div className={classes.invite_content_link}>
{address ? (
<>
{userData?.nftId ? (
<>
<span>{shortenString(userInviteLink, 15, 15)}</span>
<IconFont
onClick={() => { onClick={() => {
navigate("/mint"); copyText(userInviteLink);
}} }}
> className={classes.invite_content_icon}
<span>{t("铸造 NFT")}</span> name="fuzhi"
<IconFont color={"#fff"}
className={ />{" "}
classes.nftToken_content_nft_mint_btn_icon </>
} ) : (
name="chevronsrightshuangyoujiantou" <>
color={"#fff"} <span>{t("MINT Nft 获取邀请链接")}</span>
/> </>
</div>
<span>{t("铸造 NFT 获得代币空投")}</span>
</div>
)} )}
</> </>
) : ( ) : (
<> <>
<div className={classes.nftToken_content_userDisconnect}> <span>{t("链接钱包获取邀请链接")}</span>
<span>{t("钱包未链接,无法向您显示 NFT")}</span>
</div>
</> </>
)} )}
</>
)}
{tabIndex == 1 && (
<div className={classes.nftToken_content_token}>
<div className={classes.nftToken_content_token_top}>
<span>{t("资产金额 = 已领取 + 待处理")}</span>
</div>
<ul className={classes.nftToken_content_token_list}>
{userData?.userIncomes.map((v, i) => (
<ReceiveCom
key={i}
tokenName={v.coinName}
tokenNum={v.receive}
toReceive={v.collection}
onAssetRec={() => {
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) && <Empty />}
</ul>
</div> </div>
)}
</div>
</div>
<div className={classes.invite}> <span>
<div className={classes.invite_top}> {t(
<span>{t("邀请")}</span> "普通会员每邀请铸造一个NFT可获得一份空投福利推荐铸造20个NFT的可升级为会长团队中拥有20位会长可升级为基金会社长邀请越多级别越高福利越多。"
{address && ( )}
<span
onClick={() => {
navigate("/invitationlist");
}}
>
{t("邀请列表")}{" "}
<IconFont
name="chevronsrightshuangyoujiantou"
color={"#F3BE3C"}
/>
</span> </span>
)}
</div>
<div className={classes.invite_content}> {superiorsAddress && (
<span>{t("邀请链接")}</span>
<div className={classes.invite_content_link}>
{address ? (
<> <>
{userData?.nftId ? ( <span>{t("上级链接")}</span>
<div className={classes.superior_content_link}>
<> <>
<span>{shortenString(userInviteLink, 15, 15)}</span> <span>
{shortenString(superiorInvitationLink, 18, 18)}
</span>
<IconFont <IconFont
onClick={() => { onClick={() => {
copyText(userInviteLink); copyText(superiorInvitationLink);
}} }}
className={classes.invite_content_icon} className={classes.invite_content_icon}
name="fuzhi" name="fuzhi"
color={"#fff"} color={"#fff"}
/>{" "} />{" "}
</> </>
) : ( </div>
<div className={classes.superior_content_link}>
<> <>
<span>{t("MINT Nft 获取邀请链接")}</span> <span>{t("上级地址:")}</span>
<span>{shortenString(superiorsAddress, 15, 15)}</span>
</> </>
)} </div>
</>
) : (
<>
<span>{t("链接钱包获取邀请链接")}</span>
</> </>
)} )}
</div> </div>
</div>
<span> <div className={classes.dataDisclosure}>
{t( <span>{t("数据披露")}</span>
"普通会员每邀请铸造一个NFT可获得一份空投福利推荐铸造20个NFT的可升级为会长团队中拥有20位会长可升级为基金会社长邀请越多级别越高福利越多。" <ul className={classes.dataDisclosure_content}>
)} <li className={classes.dataDisclosure_content_item}>
</span> <span>{t("资金池")}</span>
<span>{userData?.pools || 0}</span>
</li>
<li className={classes.dataDisclosure_content_item}>
<span>{t("社长席位")}</span>
<span>{userData?.president || 0}</span>
</li>
<li className={classes.dataDisclosure_content_item}>
<span>{t("基金会社长席位")}</span>
<span>{userData?.foundation || 0}</span>
</li>
</ul>
</div> </div>
</div> </div>
</PullToRefresh>
<div className={classes.dataDisclosure}>
<span>{t("数据披露")}</span>
<ul className={classes.dataDisclosure_content}>
<li className={classes.dataDisclosure_content_item}>
<span>{t("资金池")}</span>
<span>{userData?.pools || 0}</span>
</li>
<li className={classes.dataDisclosure_content_item}>
<span>{t("社长席位")}</span>
<span>{userData?.president || 0}</span>
</li>
<li className={classes.dataDisclosure_content_item}>
<span>{t("基金会社长席位")}</span>
<span>{userData?.foundation || 0}</span>
</li>
</ul>
</div>
</div>
</> </>
); );
} }
@ -408,24 +501,26 @@ function ReceiveCom({
toReceive, toReceive,
onAssetRec, onAssetRec,
onReceive, onReceive,
coinId,
}: { }: {
tokenName: string; tokenName: string;
tokenNum: string; tokenNum: number;
toReceive: number; toReceive: number;
onAssetRec: () => void; onAssetRec: () => void;
onReceive: () => void; onReceive: () => void;
coinId: UserIncome["coinId"];
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<li className={classes.nftToken_content_token_item}> <li className={classes.nftToken_content_token_item}>
{tokenName.toUpperCase() == "USDT" && <img src={usdtBg} alt="" />} {coinId == 1 && <img src={usdtBg} alt="" />}
{tokenName.toUpperCase() == "RMOB" && <img src={RMOB_logo} alt="" />} {coinId == 2 && <img src={RMOB_logo} alt="" />}
<div> <div>
<span className={classes.nftToken_content_token_item_tokenName}> <span className={classes.nftToken_content_token_item_tokenName}>
{tokenName} {tokenName}
</span> </span>
<span className={classes.nftToken_content_token_item_tokenNum}> <span className={classes.nftToken_content_token_item_tokenNum}>
{tokenNum} {tokenNum + toReceive}
</span> </span>
<span <span
className={classes.nftToken_content_token_item_AssetRecords} className={classes.nftToken_content_token_item_AssetRecords}
@ -433,7 +528,7 @@ function ReceiveCom({
onAssetRec(); onAssetRec();
}} }}
> >
{t("资产记录")}{" "} {t("收益记录")}{" "}
<IconFont name="chevronsrightshuangyoujiantou" color={"#3680FF"} /> <IconFont name="chevronsrightshuangyoujiantou" color={"#3680FF"} />
</span> </span>
</div> </div>

View File

@ -1,11 +1,12 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-06-19 11:03:01 * @Date: 2024-06-19 11:03:01
* @LastEditTime: 2024-06-22 10:27:19 * @LastEditTime: 2024-06-26 15:21:27
* @Author: John * @Author: John
*/ */
import { api_preprelion_list } from "@/server/api"; import { api_preprelion_list } from "@/server/api";
import { PreprelionListItem } from "@/server/module"; import { PreprelionListItem } from "@/server/module";
import { getLevelName } from "@/utils";
import { Empty } from "antd-mobile"; import { Empty } from "antd-mobile";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import DataTable, { TableColumn } from "react-data-table-component"; import DataTable, { TableColumn } from "react-data-table-component";
@ -22,8 +23,10 @@ export default function () {
}, },
{ {
name: t("级别"), name: t("级别"),
selector: (row) => row.level,
grow: 4, grow: 4,
cell(row, rowIndex, column, id) {
return <div>{getLevelName(row.level, row.userType)}</div>;
},
}, },
{ {
name: t("直推NFT"), name: t("直推NFT"),

View File

@ -84,6 +84,7 @@ export default function () {
async function updateUserUpgrdeInfo() { async function updateUserUpgrdeInfo() {
const { data } = await api_get_user_upgrade_information().send({}); const { data } = await api_get_user_upgrade_information().send({});
// setUserUpgradeInfo({ ...data!.data, ...{ status: 1 } });
setUserUpgradeInfo(data?.data); setUserUpgradeInfo(data?.data);
} }
@ -94,7 +95,12 @@ export default function () {
<div className={classes.content_box}> <div className={classes.content_box}>
<div className={classes.box_item}> <div className={classes.box_item}>
<span>{t("当前级别")}</span> <span>{t("当前级别")}</span>
<span>{getLevelName(userUpgradeInfo?.level || 0)}</span> <span>
{getLevelName(
userUpgradeInfo?.level || 0,
userUpgradeInfo?.active
)}
</span>
</div> </div>
<IconFont <IconFont
className={classes.box_arrow} className={classes.box_arrow}
@ -116,7 +122,7 @@ export default function () {
<span>{t("价格说明:")}</span> <span>{t("价格说明:")}</span>
<span> <span>
{t( {t(
"升级费用xxx USDT起其中gas费2USDT剩余部分50%进入资金池另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始每升级一名社长所需铸造费用增加xxx既第二位社长升级铸造费用为xxxu+xxx*xxx=xxx USDT以此类推。", "升级费用xxx USDT起50%进入资金池另外50%平均分给所有升级成功的社长和基金会社长。自第二个社长升级开始每升级一名社长所需铸造费用增加xxx既第二位社长升级铸造费用为xxxu+xxx*xxx=xxx USDT以此类推。",
{ {
value1: userUpgradeInfo?.upgradeFees || 0, value1: userUpgradeInfo?.upgradeFees || 0,
value2: userUpgradeInfo?.proportion || "0%", value2: userUpgradeInfo?.proportion || "0%",
@ -163,7 +169,7 @@ export default function () {
upgradeLoadingtoast.current = Toast.show({ upgradeLoadingtoast.current = Toast.show({
icon: "loading", icon: "loading",
duration: 0, duration: 0,
content: t("购买中"), content: t("升级中"),
maskClickable: false, maskClickable: false,
}); });
const { data: orderRes } = await api_upgrade().send({}); const { data: orderRes } = await api_upgrade().send({});
@ -172,7 +178,7 @@ export default function () {
const buyAmount = BigInt(orderInfo.current?.buyAmount || ""); const buyAmount = BigInt(orderInfo.current?.buyAmount || "");
upGradeByContract(buyAmount, orderInfo.current?.orderNumber) upGradeByContract(buyAmount, orderInfo.current?.orderNumber)
.then((hash) => { .then((hash) => {
console.log("购买成功hash:", hash); console.log("升级成功hash:", hash);
updateUserUpgrdeInfo(); updateUserUpgrdeInfo();
startPollingCheckBuyStatus(hash); startPollingCheckBuyStatus(hash);
}) })
@ -189,7 +195,7 @@ export default function () {
<Space> <Space>
{userUpgradeInfo?.status == 1 ? ( {userUpgradeInfo?.status == 1 ? (
<> <>
{approveUsdt > 0n && <span>MINT</span>} {approveUsdt > 0n && <span>{t("升级")}</span>}
{approveUsdt === 0n && <span>{t("授权USDT")}</span>} {approveUsdt === 0n && <span>{t("授权USDT")}</span>}
</> </>
) : ( ) : (

View File

@ -1,7 +1,7 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-06-18 10:28:21 * @Date: 2024-06-18 10:28:21
* @LastEditTime: 2024-06-22 11:43:04 * @LastEditTime: 2024-07-10 11:53:39
* @Author: John * @Author: John
*/ */
import { GET, POST } from "./client"; import { GET, POST } from "./client";
@ -52,7 +52,7 @@ export function api_signUp() {
chainType: 2; chainType: 2;
}, },
any any
>({ url: "/api/account/signUp", requiresToken: false }); >({ url: "/api/account/signUp", requiresToken: false, catchErr: true });
} }
// 获取钱包签名串 // 获取钱包签名串
@ -131,3 +131,24 @@ export function api_claim_income() {
url: "/api/common/claimYourEarnings", url: "/api/common/claimYourEarnings",
}); });
} }
// 绑定邀请关系
export function api_binding_invitation_relationship() {
return POST<{ shareCode: string }, { result: boolean }>({
url: "/api/account/bindingRelationship",
});
}
// 查询用户是否绑定关系
export function api_query_whether_the_user_is_binding_relationship() {
return GET<any, { result: boolean }>({
url: "/api/account/bindOrNot",
});
}
// 获取用户上级
export function api_get_user_superiors() {
return GET<any, { address: string; shareCode: string }>({
url: "/api/user/getTheSuperior",
});
}

View File

@ -1,7 +1,7 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-06-18 10:09:21 * @Date: 2024-06-18 10:09:21
* @LastEditTime: 2024-06-21 14:47:26 * @LastEditTime: 2024-07-02 11:36:28
* @Author: John * @Author: John
*/ */
import { Client } from "@hyper-fetch/core"; import { Client } from "@hyper-fetch/core";
@ -17,9 +17,11 @@ import i18next from "i18next";
function initClient({ function initClient({
requiresToken, requiresToken,
requiresAddress, requiresAddress,
catchErr,
}: { }: {
requiresToken: boolean; requiresToken: boolean;
requiresAddress: boolean; requiresAddress: boolean;
catchErr: boolean;
}) { }) {
return new Client({ url: import.meta.env.VITE_BASE_API_URL }) return new Client({ url: import.meta.env.VITE_BASE_API_URL })
.onAuth(async (req) => { .onAuth(async (req) => {
@ -59,6 +61,7 @@ function initClient({
const resData: BASE_RESPONSE = res.data; const resData: BASE_RESPONSE = res.data;
if (resData.code !== 200 && resData.code !== 0) { if (resData.code !== 200 && resData.code !== 0) {
if (resData.msg) Toast.show({ content: resData.msg, icon: "fail" }); if (resData.msg) Toast.show({ content: resData.msg, icon: "fail" });
if (catchErr) return res;
throw new Error(resData.msg || "client on response error"); throw new Error(resData.msg || "client on response error");
} }
return res; return res;
@ -69,12 +72,14 @@ export const POST = <P = any, R = any, QueryParams = any>({
url, url,
requiresToken = true, requiresToken = true,
requiresAddress = true, requiresAddress = true,
catchErr = false,
}: { }: {
url: string; url: string;
requiresToken?: boolean; requiresToken?: boolean;
requiresAddress?: boolean; requiresAddress?: boolean;
catchErr?: boolean;
}) => { }) => {
return initClient({ requiresToken, requiresAddress }).createRequest< return initClient({ requiresToken, requiresAddress, catchErr }).createRequest<
BASE_RESPONSE<R>, BASE_RESPONSE<R>,
P, P,
any, any,
@ -89,12 +94,14 @@ export const GET = <P = any, R = any>({
url, url,
requiresToken = true, requiresToken = true,
requiresAddress = true, requiresAddress = true,
catchErr = false,
}: { }: {
url: string; url: string;
requiresToken?: boolean; requiresToken?: boolean;
requiresAddress?: boolean; requiresAddress?: boolean;
catchErr?: boolean;
}) => { }) => {
return initClient({ requiresToken, requiresAddress }).createRequest< return initClient({ requiresToken, requiresAddress, catchErr }).createRequest<
BASE_RESPONSE<R>, BASE_RESPONSE<R>,
any, any,
any, any,

View File

@ -19,15 +19,16 @@ export interface UserHomeData {
presidentNumber: number; presidentNumber: number;
userImg: string; userImg: string;
userIncomes: UserIncome[]; userIncomes: UserIncome[];
active: 0 | 1; // "0=非活跃 1=活跃用户"
} }
export interface UserIncome { export interface UserIncome {
coinId: number; coinId: 1 | 2; // 1 USDT 2 ROMB
coinName: string; coinName: string;
collection: number; collection: number;
createTime: string; createTime: string;
flag: number; flag: number;
id: number; id: number;
receive: string; receive: number;
updateTime: string; updateTime: string;
userId: number; userId: number;
} }
@ -42,6 +43,7 @@ export interface UserUpgradeInformation {
proportion: string; proportion: string;
status: 1 | 0; //1=可升级 0=不可升级 status: 1 | 0; //1=可升级 0=不可升级
upgradeFees: string; upgradeFees: string;
active: 0 | 1; // "0=非活跃 1=活跃用户"
} }
export interface NftConfigurationData { export interface NftConfigurationData {
@ -107,9 +109,9 @@ export interface NftOrder {
export interface PreprelionListItem { export interface PreprelionListItem {
address: string; address: string;
level: number; level: 0 | 1 | 2 | 3; // 0=无等级 1=会员 2=社长 3=基金会
mintNumber: number; mintNumber: number;
userType: number; userType: 0 | 1; // 0=非活跃 1=活跃用户
} }
export interface UpgradeOrder { export interface UpgradeOrder {

View File

@ -256,3 +256,59 @@
} }
} }
} }
.adm-dialog {
.adm-center-popup-body {
box-sizing: border-box !important;
border: 1px solid #fc872b !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 #fc872b !important;
.adm-dialog-button {
span {
color: #fc872b;
}
}
}
}
}
}
/* 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;
}
}

View File

@ -1,14 +1,14 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-06-17 18:19:27 * @Date: 2024-06-17 18:19:27
* @LastEditTime: 2024-06-24 14:49:16 * @LastEditTime: 2024-06-25 15:29:51
* @Author: John * @Author: John
*/ */
import { type ClassValue, clsx } from "clsx"; import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge"; import { twMerge } from "tailwind-merge";
import Toast from "antd-mobile/es/components/toast"; import Toast from "antd-mobile/es/components/toast";
import i18next from "i18next"; import i18next from "i18next";
import { Level } from "@/server/module"; import { Level, UserHomeData } from "@/server/module";
export const ua = navigator.userAgent; export const ua = navigator.userAgent;
export const isIOS = /iphone|ipad|ipod|ios/i.test(ua); export const isIOS = /iphone|ipad|ipod|ios/i.test(ua);
@ -31,7 +31,7 @@ export function shortenString(
} }
// 定义一个函数,用于获取指定参数的值 // 定义一个函数,用于获取指定参数的值
export function getUrlQueryParam(key: string): string | undefined { export function getUrlQueryParam(key: string) {
console.log(window.location); console.log(window.location);
const query: Map<string, string> = new Map(); const query: Map<string, string> = new Map();
const queryStr = window.location.href.split("?")[1]; const queryStr = window.location.href.split("?")[1];
@ -84,12 +84,16 @@ export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs)); return twMerge(clsx(inputs));
} }
export function getLevelName(level: Level) { export function getLevelName(level: Level, active?: UserHomeData["active"]) {
switch (level) { switch (level) {
case 0: case 0:
return i18next.t("普通非活跃"); return i18next.t("无等级");
case 1: case 1:
return i18next.t("普通活跃"); if (active == 1) {
return i18next.t("普通活跃");
} else {
return i18next.t("普通非活跃");
}
case 2: case 2:
return i18next.t("社长"); return i18next.t("社长");
case 3: case 3:
@ -98,3 +102,19 @@ export function getLevelName(level: Level) {
break; break;
} }
} }
export function getUrlParameterByName(name: string, url?: string) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
let regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return "";
console.log("url params:", results);
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
export function padWithZero(num: number) {
// 将数字转换为字符串并在前面补足零使总长度为5
return String(num).padStart(5, "0");
}

View File

@ -1,14 +1,16 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-06-19 15:55:07 * @Date: 2024-06-19 15:55:07
* @LastEditTime: 2024-06-24 14:01:50 * @LastEditTime: 2024-07-02 11:38:59
* @Author: John * @Author: John
*/ */
import { config } from "@/components/WalletProvider"; import { config } from "@/components/WalletProvider";
import { import {
api_binding_invitation_relationship,
api_check_account_registration, api_check_account_registration,
api_get_wallet_signature_string, api_get_wallet_signature_string,
api_login, api_login,
api_query_whether_the_user_is_binding_relationship,
api_signUp, api_signUp,
} from "@/server/api"; } from "@/server/api";
import useUserStore from "@/store/User"; import useUserStore from "@/store/User";
@ -18,9 +20,12 @@ import {
switchChain, switchChain,
getChainId, getChainId,
disconnect, disconnect,
getAccount,
} from "@wagmi/core"; } from "@wagmi/core";
import Toast from "antd-mobile/es/components/toast"; import Toast from "antd-mobile/es/components/toast";
import i18next from "i18next"; import i18next from "i18next";
import { getUrlParameterByName } from ".";
import { UrlQueryParamsKey } from "@/constants";
/** /**
* @description: * @description:
@ -101,7 +106,6 @@ export async function signAndLogin(address?: `0x${string}`): Promise<void> {
}); });
} catch (error) { } catch (error) {
// 用户拒绝签名或者遇到错误,断开链接 // 用户拒绝签名或者遇到错误,断开链接
disconnect(config);
loadingToast.close(); loadingToast.close();
loginOut(); loginOut();
throw new Error("用户拒绝签名或者遇到错误,断开链接"); throw new Error("用户拒绝签名或者遇到错误,断开链接");
@ -121,30 +125,38 @@ export async function signAndLogin(address?: `0x${string}`): Promise<void> {
useUserStore.setState((state) => { useUserStore.setState((state) => {
return { ...state, Token: loginInfoData.data?.token }; return { ...state, Token: loginInfoData.data?.token };
}); });
// TODO 判断用户是否绑定关系✔
// await checkUserBind(false);
reslove(); reslove();
loadingToast.close(); loadingToast.close();
} }
} else { } else {
const inviteCode = getUrlParameterByName(UrlQueryParamsKey.INVITE_CODE);
if (!inviteCode) {
Toast.show({ icon: "fail", content: i18next.t("无效的邀请链接") });
return loginOut();
}
// 注册 // 注册
await api_signUp().send({ const { data } = await api_signUp().send({
data: { data: {
account: address, account: address,
publicKey, publicKey,
shareCode: "", shareCode: inviteCode,
chainType: 2, chainType: 2,
}, },
}); });
await signAndLogin(address); if (data?.code === 0) {
await signAndLogin(address);
} else {
return loginOut();
}
reslove(); reslove();
loadingToast.close(); loadingToast.close();
} }
}); });
} }
export function loginOut() { export async function loginOut() {
const { connector } = getAccount(config);
await disconnect(config, { connector });
useUserStore.setState((state) => { useUserStore.setState((state) => {
return { ...state, Address: "", Token: "" }; return { ...state, Address: "", Token: "" };
}); });

3
src/vite-env.d.ts vendored
View File

@ -1,7 +1,7 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-06-17 17:20:03 * @Date: 2024-06-17 17:20:03
* @LastEditTime: 2024-06-21 13:50:16 * @LastEditTime: 2024-07-02 16:53:48
* @Author: John * @Author: John
*/ */
/// <reference types="vite/client" /> /// <reference types="vite/client" />
@ -12,6 +12,7 @@ interface ImportMetaEnv {
readonly VITE_PARTICIPATE_CHAIN_ID: number; readonly VITE_PARTICIPATE_CHAIN_ID: number;
readonly VITE_NETWORK_USDT_ADDRESS: `0x${string}`; readonly VITE_NETWORK_USDT_ADDRESS: `0x${string}`;
readonly VITE_PURCHASED_CONTRACT_ADDRESS: `0x${string}`; readonly VITE_PURCHASED_CONTRACT_ADDRESS: `0x${string}`;
readonly VITE_RECEIVE_RAMB_CONTRACT_ADDRESS: `0x${string}`;
readonly VITE_CHECK_TRANSACTION_DETAILS_URL: string; readonly VITE_CHECK_TRANSACTION_DETAILS_URL: string;
// 更多环境变量... // 更多环境变量...
readonly MODE: "development" | "production" | "test"; readonly MODE: "development" | "production" | "test";

View File

@ -1,7 +1,7 @@
/* /*
* @LastEditors: John * @LastEditors: John
* @Date: 2024-06-17 17:20:03 * @Date: 2024-06-17 17:20:03
* @LastEditTime: 2024-06-17 17:41:09 * @LastEditTime: 2024-06-24 18:48:07
* @Author: John * @Author: John
*/ */
{ {
@ -23,9 +23,6 @@
/* Linting */ /* Linting */
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"strict": true, "strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]