ffi
This commit is contained in:
parent
740e3694b4
commit
c2a22d32ca
451
README.md
451
README.md
@ -1,3 +1,454 @@
|
|||||||
运行代码指令
|
运行代码指令
|
||||||
npm run dev
|
npm run dev
|
||||||
yarn run dev
|
yarn run dev
|
||||||
|
const ERC20ABI = [
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "_nftTarget",
|
||||||
|
type: "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address[]",
|
||||||
|
name: "_manageAddress",
|
||||||
|
type: "address[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stateMutability: "nonpayable",
|
||||||
|
type: "constructor"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "user",
|
||||||
|
type: "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "nft",
|
||||||
|
type: "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: false,
|
||||||
|
internalType: "uint256[]",
|
||||||
|
name: "nftSIds",
|
||||||
|
type: "uint256[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: false,
|
||||||
|
internalType: "uint256[]",
|
||||||
|
name: "nftTIds",
|
||||||
|
type: "uint256[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "Minted",
|
||||||
|
type: "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "previousAdminRole",
|
||||||
|
type: "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "newAdminRole",
|
||||||
|
type: "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "RoleAdminChanged",
|
||||||
|
type: "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "sender",
|
||||||
|
type: "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "RoleGranted",
|
||||||
|
type: "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "sender",
|
||||||
|
type: "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "RoleRevoked",
|
||||||
|
type: "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [],
|
||||||
|
name: "DEFAULT_ADMIN_ROLE",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "",
|
||||||
|
type: "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
constant: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [],
|
||||||
|
name: "MANAGE_ROLE",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "",
|
||||||
|
type: "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
constant: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "getRoleAdmin",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "",
|
||||||
|
type: "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
constant: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "uint256",
|
||||||
|
name: "index",
|
||||||
|
type: "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "getRoleMember",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "",
|
||||||
|
type: "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
constant: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "getRoleMemberCount",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "uint256",
|
||||||
|
name: "",
|
||||||
|
type: "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
constant: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "grantRole",
|
||||||
|
outputs: [],
|
||||||
|
stateMutability: "nonpayable",
|
||||||
|
type: "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "hasRole",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "bool",
|
||||||
|
name: "",
|
||||||
|
type: "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
constant: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [],
|
||||||
|
name: "nft",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "contract IBEERC721",
|
||||||
|
name: "",
|
||||||
|
type: "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
constant: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "uint256",
|
||||||
|
name: "",
|
||||||
|
type: "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "nftMinted",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "bool",
|
||||||
|
name: "",
|
||||||
|
type: "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
constant: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "",
|
||||||
|
type: "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "uint256",
|
||||||
|
name: "",
|
||||||
|
type: "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "ownerToNFTs",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "uint256",
|
||||||
|
name: "",
|
||||||
|
type: "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
constant: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "renounceRole",
|
||||||
|
outputs: [],
|
||||||
|
stateMutability: "nonpayable",
|
||||||
|
type: "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "revokeRole",
|
||||||
|
outputs: [],
|
||||||
|
stateMutability: "nonpayable",
|
||||||
|
type: "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes4",
|
||||||
|
name: "interfaceId",
|
||||||
|
type: "bytes4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "supportsInterface",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "bool",
|
||||||
|
name: "",
|
||||||
|
type: "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
constant: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "_user",
|
||||||
|
type: "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "uint256",
|
||||||
|
name: "count",
|
||||||
|
type: "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "mintToUser",
|
||||||
|
outputs: [],
|
||||||
|
stateMutability: "nonpayable",
|
||||||
|
type: "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "_user",
|
||||||
|
type: "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "uint256[]",
|
||||||
|
name: "_nftIds",
|
||||||
|
type: "uint256[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "addNFTData",
|
||||||
|
outputs: [],
|
||||||
|
stateMutability: "nonpayable",
|
||||||
|
type: "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "_user",
|
||||||
|
type: "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "getMintableCount",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "uint256",
|
||||||
|
name: "",
|
||||||
|
type: "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
constant: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "_user",
|
||||||
|
type: "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: "getMintableNftIds",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "uint256[]",
|
||||||
|
name: "",
|
||||||
|
type: "uint256[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
constant: true
|
||||||
|
}
|
||||||
|
]
|
@ -1,3 +1,4 @@
|
|||||||
|
import request from "@/utils/request";
|
||||||
/**
|
/**
|
||||||
* begin claim badge
|
* begin claim badge
|
||||||
* @param {*} data: {id: string}
|
* @param {*} data: {id: string}
|
||||||
|
BIN
src/assets/img/badge/more-hover.png
Normal file
BIN
src/assets/img/badge/more-hover.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -11,6 +11,7 @@ import {
|
|||||||
ACTIVATE_PROXY_ABI,
|
ACTIVATE_PROXY_ABI,
|
||||||
MYSTERY_BOX_ABI,
|
MYSTERY_BOX_ABI,
|
||||||
MYSTERY_PROXY_ABI,
|
MYSTERY_PROXY_ABI,
|
||||||
|
MEDAL_REWARDS_ABI,
|
||||||
} from "@/configs/contracts";
|
} from "@/configs/contracts";
|
||||||
|
|
||||||
const AppModule = useAppStore(pinia);
|
const AppModule = useAppStore(pinia);
|
||||||
@ -116,6 +117,7 @@ export default class ChainManager {
|
|||||||
return balance;
|
return balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get amount of mystery boxes
|
* get amount of mystery boxes
|
||||||
* this method can get amount of general erc721 also
|
* this method can get amount of general erc721 also
|
||||||
|
@ -6,9 +6,10 @@ import { useUserStore } from "@/store/user";
|
|||||||
import { isMobile } from "@/utils/resize";
|
import { isMobile } from "@/utils/resize";
|
||||||
import { hasMetamask, toHexChainId } from "@/utils/chain.util";
|
import { hasMetamask, toHexChainId } from "@/utils/chain.util";
|
||||||
import { AllChains } from "@/configs/allchain";
|
import { AllChains } from "@/configs/allchain";
|
||||||
import { ERC20ABI } from "@/configs/contracts";
|
import { ERC20ABI, LIMIT_ABI, MEDAL_REWARDS_ABI } from "@/configs/contracts";
|
||||||
import { TransactionReceipt } from "web3-core";
|
import { TransactionReceipt } from "web3-core";
|
||||||
import { useEventBus } from "@vueuse/core";
|
import { useEventBus } from "@vueuse/core";
|
||||||
|
import { Global } from "@/configs/global";
|
||||||
import * as bus_event from "@/bus/event";
|
import * as bus_event from "@/bus/event";
|
||||||
import pinia from "@/store";
|
import pinia from "@/store";
|
||||||
|
|
||||||
@ -95,6 +96,7 @@ export class Blockchain {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.web3 = new Web3(this.provider);
|
this.web3 = new Web3(this.provider);
|
||||||
|
|
||||||
const chainId = await this.web3.eth.getChainId();
|
const chainId = await this.web3.eth.getChainId();
|
||||||
await this.checkChain(chainId);
|
await this.checkChain(chainId);
|
||||||
|
|
||||||
@ -126,7 +128,7 @@ export class Blockchain {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private async checkChain(chainId: number) {
|
private async checkChain(chainId: number) {
|
||||||
if (!this.chainMap.has(chainId)) {
|
if (chainId !== AVAILABLE_CHAINS[0]) {
|
||||||
// if (this.walletType === 1) {
|
// if (this.walletType === 1) {
|
||||||
try {
|
try {
|
||||||
await this.selectChain();
|
await this.selectChain();
|
||||||
@ -195,19 +197,12 @@ export class Blockchain {
|
|||||||
*/
|
*/
|
||||||
private selectChain(): Promise<number> {
|
private selectChain(): Promise<number> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
busNeedChangeChain.emit({
|
this.switchEthereumChain(AVAILABLE_CHAINS[0], (res: any)=>{
|
||||||
confirm: async (id: number) => {
|
if (res.err) {
|
||||||
console.log("select chain: ", id);
|
reject && reject(res.err)
|
||||||
this.currentChain = id;
|
return
|
||||||
if (this.provider) {
|
|
||||||
await this.switchEthereumChain();
|
|
||||||
}
|
}
|
||||||
resolve && resolve(id);
|
resolve && resolve(res.chain)
|
||||||
},
|
|
||||||
cancel: (reason: any) => {
|
|
||||||
console.log("cancel select chain: ", reason);
|
|
||||||
reject && reject(reason);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -256,6 +251,11 @@ export class Blockchain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async getContractInstance(address: string, abi: any = ERC20ABI) {
|
public async getContractInstance(address: string, abi: any = ERC20ABI) {
|
||||||
|
if (!this.web3) {
|
||||||
|
throw new Error(
|
||||||
|
"Web3 instance is not initialized. Please call `initWeb3` method after user login."
|
||||||
|
);
|
||||||
|
}
|
||||||
if (!this.instanceCacheMap.has(address)) {
|
if (!this.instanceCacheMap.has(address)) {
|
||||||
const instance = new this.web3.eth.Contract(abi, address, {
|
const instance = new this.web3.eth.Contract(abi, address, {
|
||||||
from: AppModule.accountId,
|
from: AppModule.accountId,
|
||||||
@ -344,24 +344,15 @@ export class Blockchain {
|
|||||||
* @param {() => void} cb
|
* @param {() => void} cb
|
||||||
* @return {Promise<void>}
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async switchEthereumChain(chainId?: number, cb?: () => void) {
|
async switchEthereumChain(chainId?: number, cb?: (res: any) => void) {
|
||||||
chainId = chainId || this.currentChain;
|
chainId = chainId || AVAILABLE_CHAINS[0];
|
||||||
const hexChainId = toHexChainId(chainId);
|
const hexChainId = toHexChainId(chainId);
|
||||||
const onChainChange = (chainId: string) => {
|
const onChainChange = (chainId: string) => {
|
||||||
console.log("switchEthereumChain: ", chainId);
|
console.log("switchEthereumChain: ", chainId);
|
||||||
this.provider.removeListener("chainChanged", onChainChange);
|
this.provider.removeListener("chainChanged", onChainChange);
|
||||||
cb && cb();
|
cb && cb({chain: chainId});
|
||||||
};
|
};
|
||||||
this.provider.on("chainChanged", onChainChange);
|
this.provider.on("chainChanged", onChainChange);
|
||||||
try {
|
|
||||||
await this.provider.request({
|
|
||||||
method: "wallet_switchEthereumChain",
|
|
||||||
params: [{ chainId: hexChainId }],
|
|
||||||
});
|
|
||||||
console.log("switch chain success");
|
|
||||||
} catch (e: any) {
|
|
||||||
console.log("switch chain error: ", e);
|
|
||||||
if (e.code === 4902 || e.message.indexOf("Unrecognized chain ID") >= 0) {
|
|
||||||
try {
|
try {
|
||||||
const data = this.chainMap.get(chainId)!;
|
const data = this.chainMap.get(chainId)!;
|
||||||
await this.provider.request({
|
await this.provider.request({
|
||||||
@ -384,9 +375,7 @@ export class Blockchain {
|
|||||||
} catch (addError) {
|
} catch (addError) {
|
||||||
console.error("add chain error: ", addError);
|
console.error("add chain error: ", addError);
|
||||||
this.provider.removeListener("chainChanged", onChainChange);
|
this.provider.removeListener("chainChanged", onChainChange);
|
||||||
}
|
cb && cb({err: addError})
|
||||||
}
|
|
||||||
// console.error(e)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,6 +444,38 @@ export class Blockchain {
|
|||||||
console.log("increaseAllowance: ", res);
|
console.log("increaseAllowance: ", res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async totalSupply(address: string) {
|
||||||
|
const coinInstance: any = await this.getContractInstance(
|
||||||
|
Global.LIMIT_ABI_Address,
|
||||||
|
LIMIT_ABI
|
||||||
|
);
|
||||||
|
const res = await coinInstance.methods.totalSupply().call({ gas: 1000000 });
|
||||||
|
console.log("totalSupply: ", res);
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
// 获取当前用户可mint的数量
|
||||||
|
public async getMintableCount(address?: string) {
|
||||||
|
// address = address || //TODO: current address
|
||||||
|
const coinInstance: any = await this.getContractInstance(
|
||||||
|
Global.MEDAL_REWARDS_Address,
|
||||||
|
MEDAL_REWARDS_ABI
|
||||||
|
);
|
||||||
|
const res = await coinInstance.methods
|
||||||
|
.getMintableCount(AppModule.accountId)
|
||||||
|
.call({ gas: 1000000 });
|
||||||
|
console.log("getMintableCount: ", res);
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
// 获取当前用户的mint总数
|
||||||
|
public async supplyLimit(address: string) {
|
||||||
|
const coinInstance: any = await this.getContractInstance(
|
||||||
|
Global.LIMIT_ABI_Address,
|
||||||
|
LIMIT_ABI
|
||||||
|
);
|
||||||
|
const res = await coinInstance.methods.supplyLimit().call({ gas: 1000000 });
|
||||||
|
console.log("supplyLimit: ", res);
|
||||||
|
return res
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @param {string} address
|
* @param {string} address
|
||||||
* @param {string | null} account
|
* @param {string | null} account
|
||||||
|
@ -47,7 +47,7 @@ import { useCopyToClipboard } from "./../../hooks/useCopyToClipboard";
|
|||||||
const AppModule = useAppStore();
|
const AppModule = useAppStore();
|
||||||
const chain = useChainStore();
|
const chain = useChainStore();
|
||||||
const app = useAppStore();
|
const app = useAppStore();
|
||||||
|
const emit = defineEmits(['login-success'])
|
||||||
|
|
||||||
const { copied, copyToClipboard } = useCopyToClipboard(AppModule.accountId);
|
const { copied, copyToClipboard } = useCopyToClipboard(AppModule.accountId);
|
||||||
const message = copied.value
|
const message = copied.value
|
||||||
@ -64,14 +64,16 @@ const formatAddress = computed(() => {
|
|||||||
async function login(event) {
|
async function login(event) {
|
||||||
if (!chain.logined) {
|
if (!chain.logined) {
|
||||||
await chain.chainManager.login();
|
await chain.chainManager.login();
|
||||||
|
|
||||||
chain.logined = chain.chainManager.isLogined;
|
chain.logined = chain.chainManager.isLogined;
|
||||||
|
emit('login-success');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const logout = async () => {
|
const logout = async () => {
|
||||||
await chain.chainManager.logout();
|
await chain.chainManager.logout();
|
||||||
|
|
||||||
chain.logined = chain.chainManager.isLogined;
|
chain.logined = chain.chainManager.isLogined;
|
||||||
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ export const ALL_PROVIDERS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const AVAILABLE_CHAINS = env === "production" ? [321] : [322];
|
export const AVAILABLE_CHAINS = env === "production" ? [137] : [80001];
|
||||||
|
|
||||||
export const OFFICE_ACCOUNT =
|
export const OFFICE_ACCOUNT =
|
||||||
env === "production"
|
env === "production"
|
||||||
|
File diff suppressed because it is too large
Load Diff
4
src/configs/global.ts
Normal file
4
src/configs/global.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export namespace Global {
|
||||||
|
export const MEDAL_REWARDS_Address: string = "0xC0DA6D9d8AaDCFf7BD6d69B8b46948dD40BF0dec"; // 分发地址
|
||||||
|
export const LIMIT_ABI_Address: string = "0x5b36329D0DA1F56eD60F3C5DE1855c8dE0440140"; // 徽章地址
|
||||||
|
}
|
@ -67,7 +67,7 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
if (!res.errcode && res.data?.token) {
|
if (!res.errcode && res.data?.token) {
|
||||||
accountId.value = account;
|
accountId.value = account;
|
||||||
setToken(res.data.token);
|
setToken(res.data.token);
|
||||||
|
glodata.token = getToken();
|
||||||
setAccountId(account);
|
setAccountId(account);
|
||||||
AppModule.updateAccount(account);
|
AppModule.updateAccount(account);
|
||||||
AppModule.updateToken(res.data.token);
|
AppModule.updateToken(res.data.token);
|
||||||
@ -83,6 +83,9 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
removeToken();
|
removeToken();
|
||||||
token.value = "";
|
token.value = "";
|
||||||
accountId.value = "";
|
accountId.value = "";
|
||||||
|
glodata.token = '';
|
||||||
|
glodata.accountId=''
|
||||||
|
AppModule.updateToken("");
|
||||||
AppModule.updateAccount("");
|
AppModule.updateAccount("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="my-container">
|
<div class="my-container">
|
||||||
<NavBar></NavBar>
|
<NavBar @login-success="fetchData"></NavBar>
|
||||||
<div class="content-top">
|
<div class="content-top">
|
||||||
<div class="text-left">
|
<div class="text-left">
|
||||||
<img src="../assets/img/badge/left-text.png" alt="" />
|
<img src="../assets/img/badge/left-text.png" alt="" />
|
||||||
@ -20,7 +20,7 @@
|
|||||||
<div class="card shadow-md rounded cards-container">
|
<div class="card shadow-md rounded cards-container">
|
||||||
<div></div>
|
<div></div>
|
||||||
<div
|
<div
|
||||||
class="card-title text-xl mb-8 text-yellow-color font-poppins-semiBoldItalic cards-container"
|
class="card-title text-xl text-yellow-color font-poppins-semiBoldItalic cards-container"
|
||||||
>
|
>
|
||||||
<div>GENESIS</div>
|
<div>GENESIS</div>
|
||||||
</div>
|
</div>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="genesicard">
|
<div class="genesicard">
|
||||||
<div class="genesis-title pt-24 font-firaSans-blackItalic">
|
<div class="genesis-title font-firaSans-blackItalic">
|
||||||
Genesis NFT <br />
|
Genesis NFT <br />
|
||||||
holder Only
|
holder Only
|
||||||
</div>
|
</div>
|
||||||
@ -61,20 +61,29 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="ml-3">December 1 (st), 2022</div>
|
<div class="ml-3">December 1 (st), 2022</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="december-number">2000 / 4000</div>
|
<div class="december-number">
|
||||||
|
{{ totalSupply || "0" }} / {{ supplyLimit || "0" }}
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
:class="isbtn === true ? 'disabled-claim' : 'claim'"
|
:class="mintableCount == 0 ? 'disabled-claim' : 'claim'"
|
||||||
@click="handClaimBadge"
|
@click="handClaimBadge"
|
||||||
>
|
>
|
||||||
<div class="claim-item">Claim your Airdorp</div>
|
<div class="claim-item">Claim your Airdorp</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="dis-msg">
|
<div class="dis-msg">
|
||||||
<div class="msg">You’re not eligible for this stage.<img class="rabbit" src="../assets/img/badge/rabbit.png" alt=""></div>
|
<div class="msg">
|
||||||
|
{{ message
|
||||||
|
}}<img
|
||||||
|
class="rabbit"
|
||||||
|
src="../assets/img/badge/rabbit.png"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card shadow-md rounded cards-container">
|
<div class="card shadow-md rounded cards-container">
|
||||||
<div
|
<div
|
||||||
class="text-xl font-bold font-poppins-semiBoldItalic card-title-right mb-4 p-3 text-black-color-300 cards-container"
|
class="text-xl font-bold font-poppins-semiBoldItalic card-title-right text-black-color-300 cards-container"
|
||||||
>
|
>
|
||||||
EXPLORER
|
EXPLORER
|
||||||
</div>
|
</div>
|
||||||
@ -91,7 +100,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="timeline">
|
<div class="timeline">
|
||||||
<div class="timeline-boder flex justify-center pt-12">
|
<div class="timeline-boder flex justify-center pt-6">
|
||||||
<img src="../assets/img/badge/timeline.png" alt="" />
|
<img src="../assets/img/badge/timeline.png" alt="" />
|
||||||
</div>
|
</div>
|
||||||
<div class="pt-2">
|
<div class="pt-2">
|
||||||
@ -103,6 +112,7 @@
|
|||||||
<li>Beta Test I</li>
|
<li>Beta Test I</li>
|
||||||
<li>Beta Test II</li>
|
<li>Beta Test II</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div class="coming">Coming Soon</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -127,19 +137,25 @@ import {
|
|||||||
import { useAppStore } from "@/store/app";
|
import { useAppStore } from "@/store/app";
|
||||||
import { useRouter, useRoute } from "vue-router";
|
import { useRouter, useRoute } from "vue-router";
|
||||||
import { useMouse, useRafFn } from "@vueuse/core";
|
import { useMouse, useRafFn } from "@vueuse/core";
|
||||||
|
import { beginClaim, checkClaimStatus } from "../api/badge";
|
||||||
import { useMouseRotation } from "../hooks/useMouseRotation";
|
import { useMouseRotation } from "../hooks/useMouseRotation";
|
||||||
import NavBar from "@/components/layout/NavBar.vue";
|
import NavBar from "@/components/layout/NavBar.vue";
|
||||||
import ImageTextModal from "../components/global/ImageTextModal.vue";
|
import ImageTextModal from "../components/global/ImageTextModal.vue";
|
||||||
|
import { useChainStore } from "@/store/chain";
|
||||||
|
const AppModule = useAppStore();
|
||||||
const scrollOffset = ref("0%");
|
const scrollOffset = ref("0%");
|
||||||
const parallaxFactor = 0.135; // 视差滚动系数,可以根据需要调整
|
const parallaxFactor = 0.135; // 视差滚动系数,可以根据需要调整
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
const isbtn = ref(false);
|
const canClaim = ref(false);
|
||||||
|
const chain = useChainStore();
|
||||||
|
const totalSupply = ref(0);
|
||||||
|
const mintableCount = ref(0);
|
||||||
|
const supplyLimit = ref(0);
|
||||||
|
const message = ref("");
|
||||||
const handlHero = () => {
|
const handlHero = () => {
|
||||||
visible.value = true;
|
visible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleScroll = () => {
|
const handleScroll = () => {
|
||||||
const currentScrollTop =
|
const currentScrollTop =
|
||||||
window.pageYOffset || document.documentElement.scrollTop;
|
window.pageYOffset || document.documentElement.scrollTop;
|
||||||
@ -165,8 +181,62 @@ const {
|
|||||||
stopTracking: stopTracking2,
|
stopTracking: stopTracking2,
|
||||||
} = useMouseRotation();
|
} = useMouseRotation();
|
||||||
|
|
||||||
const handClaimBadge = () => {
|
const handClaimBadge = async () => {
|
||||||
isbtn.value = true;
|
if (mintableCount.value == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!chain.logined) {
|
||||||
|
await chain.chainManager.login();
|
||||||
|
chain.logined = chain.chainManager.isLogined;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
message.error("登录失败,请稍后重试");
|
||||||
|
console.error(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 调用 beginClaim API
|
||||||
|
const res = await beginClaim(1);
|
||||||
|
// message.loading("领取中,请稍等...", 0);
|
||||||
|
console.log("领取失败,请稍后重试!", res.data.taskId);
|
||||||
|
// 轮询检查 claim 任务状态
|
||||||
|
let status = 0;
|
||||||
|
let timer;
|
||||||
|
while (status !== 9 && status !== 10) {
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
timer = setTimeout(resolve, 5000); // 每隔5秒查询一次
|
||||||
|
});
|
||||||
|
const resStatus = await checkClaimStatus(res.data.taskId);
|
||||||
|
status = resStatus.data.status;
|
||||||
|
console.log("status", resStatus.data.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// message.destroy(); // 销毁 loading message
|
||||||
|
|
||||||
|
if (status === 9) {
|
||||||
|
console.log("领取成功!");
|
||||||
|
message.value = "claim success!";
|
||||||
|
clearTimeout(timer); // 清除定时器
|
||||||
|
// message.success("领取成功!");
|
||||||
|
} else if (status === 10) {
|
||||||
|
console.log("领取失败,请稍后重试!");
|
||||||
|
message.value = "claim failure!";
|
||||||
|
clearTimeout(timer); // 清除定时器
|
||||||
|
// message.error("领取失败,请稍后重试");
|
||||||
|
}
|
||||||
|
if (status === 0) {
|
||||||
|
message.value = "claiming !";
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// message.destroy();
|
||||||
|
// message.error("领取过程中发生错误,请稍后重试");
|
||||||
|
console.log("领取过程中发生错误,请稍后重试!");
|
||||||
|
// clearTimeout(timer); // 清除定时器
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const bgTranslateX = ref(0);
|
const bgTranslateX = ref(0);
|
||||||
@ -178,12 +248,34 @@ const handleScrolls = () => {
|
|||||||
bgTranslateX.value -= scrollDelta / 3; // 背景图片水平方向移动的速度
|
bgTranslateX.value -= scrollDelta / 3; // 背景图片水平方向移动的速度
|
||||||
scrollPos.value = newScrollPos;
|
scrollPos.value = newScrollPos;
|
||||||
};
|
};
|
||||||
|
const fetchData = async () => {
|
||||||
|
try {
|
||||||
|
// 获取总数
|
||||||
|
totalSupply.value = await chain.chainManager.bc.totalSupply();
|
||||||
|
|
||||||
onMounted(() => {
|
//获取可mint的数量
|
||||||
|
mintableCount.value = await chain.chainManager.bc.getMintableCount();
|
||||||
|
|
||||||
|
mintableCount.value == 0
|
||||||
|
? (message.value = "You’re not eligible for this stage.")
|
||||||
|
: "";
|
||||||
|
//获取当前用户的mint总数
|
||||||
|
supplyLimit.value = await chain.chainManager.bc.supplyLimit();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching data:", error);
|
||||||
|
}
|
||||||
|
console.log("totalSupply.value:", totalSupply.value);
|
||||||
|
console.log("mintableCount.value:", mintableCount.value);
|
||||||
|
console.log("supplyLimit.value:", supplyLimit.value);
|
||||||
|
};
|
||||||
|
// 初始化时获取数据
|
||||||
|
onMounted(async () => {
|
||||||
|
if (AppModule.accountId) {
|
||||||
|
await fetchData();
|
||||||
|
}
|
||||||
window.addEventListener("scroll", handleScroll);
|
window.addEventListener("scroll", handleScroll);
|
||||||
window.addEventListener("scroll", handleScrolls);
|
window.addEventListener("scroll", handleScrolls);
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
window.removeEventListener("scroll", handleScroll);
|
window.removeEventListener("scroll", handleScroll);
|
||||||
window.removeEventListener("scroll", handleScrolls);
|
window.removeEventListener("scroll", handleScrolls);
|
||||||
@ -207,7 +299,7 @@ onUnmounted(() => {
|
|||||||
.star-bg {
|
.star-bg {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 30px;
|
left: 30px;
|
||||||
top:30px;
|
top: 30px;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
@ -220,7 +312,7 @@ onUnmounted(() => {
|
|||||||
.bg {
|
.bg {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: -10px;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: -2;
|
z-index: -2;
|
||||||
@ -233,7 +325,7 @@ onUnmounted(() => {
|
|||||||
.text-left {
|
.text-left {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 85px;
|
left: 85px;
|
||||||
bottom: 30px;
|
bottom: 10px;
|
||||||
animation: slide-up 1s ease-out;
|
animation: slide-up 1s ease-out;
|
||||||
}
|
}
|
||||||
.text-right {
|
.text-right {
|
||||||
@ -250,8 +342,8 @@ onUnmounted(() => {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #ffb900;
|
color: #ffb900;
|
||||||
}
|
}
|
||||||
.timeline{
|
.timeline {
|
||||||
width:1188px;
|
width: 1188px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
}
|
}
|
||||||
@ -263,16 +355,32 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
.card-title {
|
.card-title {
|
||||||
font-size: 80px;
|
font-size: 80px;
|
||||||
|
margin-bottom: 19px;
|
||||||
// font-family: "Poppins";
|
// font-family: "Poppins";
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
color: #ffb900;
|
color: #ffb900;
|
||||||
|
position: relative;
|
||||||
line-height: 60px;
|
line-height: 60px;
|
||||||
background: linear-gradient(180deg, #f9fe1d 0%, #ffbb17 100%);
|
background: linear-gradient(180deg, #f9fe1d 0%, #ffbb17 100%);
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
}
|
}
|
||||||
|
.card-title::after {
|
||||||
|
content: "";
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
right: 125px;
|
||||||
|
bottom: 3px;
|
||||||
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
|
background: #fcde1a;
|
||||||
|
margin-left: 5px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
.card-title-right {
|
.card-title-right {
|
||||||
font-size: 40px;
|
font-size: 40px;
|
||||||
|
margin-top: 16px;
|
||||||
|
text-align: center;
|
||||||
// font-family: "Fira Sans";
|
// font-family: "Fira Sans";
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
@ -307,7 +415,7 @@ p {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
&:hover {
|
&:hover {
|
||||||
background: url("../assets/img/badge/more.png");
|
background: url("../assets/img/badge/more-hover.png");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.btn-more-right {
|
.btn-more-right {
|
||||||
@ -324,6 +432,15 @@ p {
|
|||||||
color: #a7a7a7;
|
color: #a7a7a7;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
|
.coming {
|
||||||
|
position: absolute;
|
||||||
|
top: -90px;
|
||||||
|
left: 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: "Poppins-Regular";
|
||||||
|
font-weight: 400;
|
||||||
|
color: #a7a7a7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.btn-more-right:hover .dropdown-menu {
|
.btn-more-right:hover .dropdown-menu {
|
||||||
display: block;
|
display: block;
|
||||||
@ -336,6 +453,7 @@ p {
|
|||||||
left: 0;
|
left: 0;
|
||||||
// background-color: white;
|
// background-color: white;
|
||||||
background: url("../assets/img/badge/dropdown-menu-bg.png") no-repeat;
|
background: url("../assets/img/badge/dropdown-menu-bg.png") no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
min-width: 145px;
|
min-width: 145px;
|
||||||
// box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
|
// box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
@ -345,12 +463,20 @@ p {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-menu li {
|
.dropdown-menu li {
|
||||||
padding: 4px 10px;
|
padding: 2px 10px;
|
||||||
|
}
|
||||||
|
.dropdown-menu li::after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
border-bottom: 1px solid #838383;
|
||||||
|
margin-top: -1px; /* 调整下划线与文字之间的间距 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-menu li:hover {
|
.dropdown-menu li:hover {
|
||||||
// background-color: #f1f1f1;
|
// background-color: #f1f1f1;
|
||||||
}
|
}
|
||||||
|
.dropdown-menu li:last-child::after {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
.card-top {
|
.card-top {
|
||||||
width: 450px;
|
width: 450px;
|
||||||
height: 450px;
|
height: 450px;
|
||||||
@ -443,6 +569,7 @@ p {
|
|||||||
.genesis-title {
|
.genesis-title {
|
||||||
font-size: 40px;
|
font-size: 40px;
|
||||||
letter-spacing: 3px;
|
letter-spacing: 3px;
|
||||||
|
margin-top: 75px;
|
||||||
// font-family: "Fira Sans";
|
// font-family: "Fira Sans";
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
@ -452,7 +579,7 @@ p {
|
|||||||
position: relative; /* 添加相对定位以便伪元素定位 */
|
position: relative; /* 添加相对定位以便伪元素定位 */
|
||||||
width: 302px;
|
width: 302px;
|
||||||
margin-left: 39px;
|
margin-left: 39px;
|
||||||
margin-right: 167px;
|
margin-right: 162px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.genesicard::before {
|
.genesicard::before {
|
||||||
@ -489,7 +616,7 @@ p {
|
|||||||
font-family: Arial;
|
font-family: Arial;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 26px;
|
||||||
// line-height: 60px;
|
// line-height: 60px;
|
||||||
}
|
}
|
||||||
.disabled-claim {
|
.disabled-claim {
|
||||||
@ -589,7 +716,6 @@ p {
|
|||||||
height: 50px;
|
height: 50px;
|
||||||
margin-top: 41px;
|
margin-top: 41px;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-family: "Poppins";
|
font-family: "Poppins";
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
@ -597,12 +723,12 @@ p {
|
|||||||
background: rgba(255, 255, 255, 0.04);
|
background: rgba(255, 255, 255, 0.04);
|
||||||
border: 1px solid #353535;
|
border: 1px solid #353535;
|
||||||
border-radius: 12px 0px 12px 0px;
|
border-radius: 12px 0px 12px 0px;
|
||||||
.msg{
|
.msg {
|
||||||
margin-left: 21px;
|
margin-left: 21px;
|
||||||
position: relative;
|
position: relative;
|
||||||
.rabbit{
|
.rabbit {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: -6px;
|
||||||
top: -24px;
|
top: -24px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,55 +1,57 @@
|
|||||||
|
<!-- MedalApp.vue -->
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<h1>可铸造的 NFT 数量:{{ mintableCount }}</h1>
|
<h1>可领取的勋章数量:{{ mintableCount }}</h1>
|
||||||
<button @click="mintNFTs">领取勋章</button>
|
<button @click="mintMedals">领取勋章</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { ethers } from 'ethers';
|
import { ethers } from 'ethers';
|
||||||
import NftDistributorABI from './NftDistributorABI.json'; // 从编译后的合约中导入 ABI
|
import MEDAL_REWARDS_ABI from './MEDAL_REWARDS_ABI.json'; // 从编译后的合约中导入 ABI
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
setup() {
|
setup() {
|
||||||
const mintableCount = ref(0);
|
const mintableCount = ref(0);
|
||||||
const nftDistributorAddress = '0x123...'; // 替换为实际的合约地址
|
const medalRewardsAddress = '0x123...'; // 替换为实际的合约地址
|
||||||
const provider = new ethers.providers.Web3Provider(window.ethereum); // 使用 MetaMask 提供的以太坊 provider
|
const provider = new ethers.providers.Web3Provider(window.ethereum); // 使用 MetaMask 提供的以太坊 provider
|
||||||
const nftDistributorContract = new ethers.Contract(nftDistributorAddress, NftDistributorABI, provider);
|
const medalRewardsContract = new ethers.Contract(medalRewardsAddress, MEDAL_REWARDS_ABI, provider);
|
||||||
|
|
||||||
const loadMintableCount = async () => {
|
const loadMintableCount = async () => {
|
||||||
try {
|
try {
|
||||||
const userAddress = await provider.getSigner().getAddress(); // 获取当前用户的地址
|
const userAddress = await provider.getSigner().getAddress(); // 获取当前用户的地址
|
||||||
const count = await nftDistributorContract.getMintableCount(userAddress);
|
const count = await medalRewardsContract.getMintableCount(userAddress);
|
||||||
mintableCount.value = count.toNumber();
|
mintableCount.value = count.toNumber();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching mintable count:', error);
|
console.error('Error fetching mintable count:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const mintNFTs = async () => {
|
const mintMedals = async () => {
|
||||||
try {
|
try {
|
||||||
const signer = provider.getSigner(); // 获取当前用户的签名器
|
const signer = provider.getSigner(); // 获取当前用户的签名器
|
||||||
const userAddress = await signer.getAddress(); // 获取当前用户的地址
|
const userAddress = await signer.getAddress(); // 获取当前用户的地址
|
||||||
const contractWithSigner = nftDistributorContract.connect(signer);
|
const contractWithSigner = medalRewardsContract.connect(signer);
|
||||||
|
|
||||||
const tx = await contractWithSigner.mintToUser(userAddress, mintableCount.value);
|
const tx = await contractWithSigner.mintToUser(userAddress, mintableCount.value);
|
||||||
await tx.wait(); // 等待交易被确认
|
await tx.wait(); // 等待交易被确认
|
||||||
|
|
||||||
// 重新加载可铸造的 NFT 数量,因为用户已经铸造了 NFT
|
// 重新加载可领取的勋章数量,因为用户已经领取了勋章
|
||||||
await loadMintableCount();
|
await loadMintableCount();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error minting NFTs:', error);
|
console.error('Error minting medals:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 页面载入时获取可铸造的 NFT 数量
|
// 页面载入时获取可领取的勋章数量
|
||||||
loadMintableCount();
|
loadMintableCount();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
mintableCount,
|
mintableCount,
|
||||||
mintNFTs,
|
mintMedals,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user