CounterFireGames/src/chain/ChainManager.ts
2023-12-27 12:02:05 +08:00

279 lines
6.9 KiB
TypeScript

import { Blockchain } from "@/chain/blockchain";
import { getNonce } from "@/api/User";
import pinia from "@/store";
import { useAppStore } from "@/store/app";
import { useUserStore } from "@/store/user";
import { message } from "ant-design-vue";
import { Chain } from "@/chain/Chain";
import { AVAILABLE_CHAINS } from "@/configs/configchain";
import { AllChains } from "@/configs/allchain";
import {
ACTIVATE_PROXY_ABI,
MYSTERY_BOX_ABI,
MYSTERY_PROXY_ABI
} from "@/configs/contracts";
const AppModule = useAppStore(pinia);
const UserModule = useUserStore();
export default class ChainManager {
bc: Blockchain;
instanceMap: Map<string, any>;
public chainMap: Map<number, any> = new Map();
private _availableChains: Map<number, any> = new Map();
constructor() {
this.bc = new Blockchain();
this.instanceMap = new Map();
for (const data of AllChains) {
this.chainMap.set(data.id, data);
}
}
get availableChains() {
if (this._availableChains.size === 0) {
for (const id of AVAILABLE_CHAINS) {
const d = this.chainMap.get(id);
if (d) {
this._availableChains.set(id, d);
}
}
}
return this._availableChains;
}
public async init() {
if (this.bc.isWalletConnect) {
try {
await this.bc.connect();
} catch (err) {
console.log("connect chain error: ", err);
}
}
}
get isLogined() {
return !!UserModule.token && !!AppModule.step;
}
public async logout() {
await this.bc.disconnect();
}
public get currentChain() {
return this.bc.currentChain;
}
public async login(type:any) {
if (!AppModule.step) {
try {
await this.bc.connect(true,type);
await this.checkNance();
} catch (err) {
message.error(err.message, 5);
this.bc.walletType = 0
await this.bc.disconnect();
await Promise.reject(err);
}
}
}
public async checkNance() {
try {
const preRequest: any = await getNonce();
let nonce = preRequest.nonce + "";
const tips = preRequest.data?.tips;
AppModule.updateNonce(nonce);
await UserModule.Login({
bcInstance: this.bc,
account: AppModule.accountId,
chainId: AppModule.chainId,
nonce,
tips,
});
AppModule.updateStep(1);
} catch (err) {
this.bc.walletType = 0
console.log(err);
await Promise.reject(err);
}
}
public async getInstance(address: string, chainId: number, abi?: any) {
const key = `${chainId}_${address}`;
if (!this.instanceMap.has(key)) {
const chain = new Chain(this.chainMap.get(chainId)!.rpc);
const coinInstance = await chain.initContractInstance(address, abi);
this.instanceMap.set(key, coinInstance);
}
return this.instanceMap.get(key);
}
public async getBalance(address: string, chainId: number) {
const coinInstance = await this.getInstance(address, chainId);
const balance = await coinInstance.methods
.balanceOf(AppModule.accountId)
.call();
console.log("balance: ", balance);
return balance;
}
/**
* get amount of mystery boxes
* this method can get amount of general erc721 also
* @param {string} address
* @param {number} chainId
* @return {Promise<any>}
*/
public async getNftBalance(address: string, chainId: number) {
const coinInstance = await this.getInstance(
address,
chainId,
MYSTERY_BOX_ABI
);
const balance = await coinInstance.methods
.balanceOf(AppModule.accountId)
.call();
console.log("nft balance: ", balance);
return balance;
}
/**
* Get NFT list of current user
* @param {string} address NFT address
* @param {number} chainId chain id
* @param {number} start
* @param {number} page
*/
public async getNftList(
address: string,
chainId: number,
start = 0,
page = 8
) {
const nftInstance = await this.getInstance(
address,
chainId,
MYSTERY_BOX_ABI
);
return nftInstance.methods
.userTokens(AppModule.accountId, start, page)
.call();
}
/**
* Get NFT of current user with index
* @param {string} address
* @param {number} chainId
* @param {number} index
* @return {Promise<any>}
*/
public async getNftIdOfIndex(
address: string,
chainId: number,
index: number
) {
const nftInstance = await this.getInstance(
address,
chainId,
MYSTERY_BOX_ABI
);
const nftId = await nftInstance.methods
.tokenOfOwnerByIndex(AppModule.accountId, index)
.call();
console.log(
`address: ${address}, chainId: ${chainId}, index: ${index}, token: ${nftId}`
);
return nftId;
}
/**
* Open one mystery box
* @param {string} address address of mystery box contract on current chain
* @param {string} boxId nftid of mystery box
* @param {number[]} tokenIds
* @param {string} nonce
* @param {string} signature
* @return {Promise<any>}
*/
public async openMysteryBox(
address: string,
boxId: string,
tokenIds: number[],
nonce: string,
signature: string
) {
const proxyInstance = await this.bc.getContractInstance(
address,
MYSTERY_PROXY_ABI
);
// get transactionHash and upload to server for verify
return proxyInstance.methods
.openBox(boxId, tokenIds, nonce, signature)
.send({ gas: 1000000 });
}
/**
* activate one nft with 18 digital id
* @param {string} address
* @param {string} nftOld
* @param {string} nftNew
* @param {number} nftType
* @param {string} nonce
* @param {string} signature
* @return {Promise<any>}
*/
public async activateOneNft(
address: string,
nftOld: string,
nftNew: string,
nftType: number,
nonce: string,
signature: string
) {
const nftProxyInstance = await this.bc.getContractInstance(
address,
ACTIVATE_PROXY_ABI
);
const gas = await nftProxyInstance.methods
.activateOne(nftOld, nftNew, nftType, nonce, signature)
.estimateGas({ gas: 1000000 });
console.log("nftProxyInstance activateOne need gas: ", gas);
return nftProxyInstance.methods
.activateOne(nftOld, nftNew, nftType, nonce, signature)
.send({ gas: (gas * 1.1) | 0 });
}
public async transferToAccount({
to,
amount,
chainId,
address,
}: {
to: string;
amount: number;
chainId: number;
address: string;
}) {
const self = this;
if (chainId !== this.bc.currentChain) {
return new Promise((resolve, reject) => {
this.bc.switchEthereumChain(chainId, function () {
self.bc
.transferToAccount(to, amount, address)
.then((res) => {
resolve && resolve(res);
})
.catch((err) => {
reject && reject(err);
});
});
});
} else {
return this.bc.transferToAccount(to, amount, address);
}
}
}