cebg-website/src/chain/ChainManager.ts
huangjinming 0ce1737c1b fix
2023-03-08 17:53:41 +08:00

253 lines
7.2 KiB
TypeScript

import { Blockchain } from '@/chain/blockchain'
import { getNonce } from '@/api/User'
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();
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()
await this.getNance()
} 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() {
if (!AppModule.step) {
try {
await this.bc.connect(true)
await this.checkNance()
} catch (err) {
message.error(err.message, 5)
await Promise.reject(err)
}
}
}
public async checkNance() {
try {
let nonce = AppModule.nonce
if (!nonce) {
const preRequest: any = await getNonce({
account: AppModule.accountId,
net_id: AppModule.chainId
})
nonce = preRequest.nonce + ''
AppModule.updateNonce(nonce)
}
await UserModule.Login({
bcInstance: this.bc,
account: AppModule.accountId,
chainId: AppModule.chainId,
nonce
})
AppModule.updateStep(1)
} catch (err) {
console.log(err)
await Promise.reject(err)
}
}
public async getNance() {
console.log('need get nance')
try {
const preRequest: any = await getNonce({
account: AppModule.accountId,
net_id: AppModule.chainId
})
console.log('success get nonce: ', preRequest)
// if need check sign and has nonce val, store it
if (preRequest.state) {
AppModule.updateStep(1)
} else if (!preRequest.state && preRequest.nonce) {
if (UserModule.token) {
await UserModule.Logout()
}
AppModule.updateStep(0)
}
if (preRequest.nonce) {
AppModule.updateNonce(preRequest.nonce + '')
}
} catch (err) {
message.error('Error get login nonce', 5);
}
}
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)
}
}
}