import { ethers } from 'ethers' import { apiUnlockOrMint, apiMintNft } from '@/utils/marketplace' import { BlockChain } from "@/components/chain/BlockChain" const lockAbi = [ 'function lock(address nft, address to, uint256[] tokenIds) external' ] const erc721Abi = [ 'function approve(address to, uint256 tokenId) external', 'function getApproved(uint256 tokenId) public view returns (address)' ] const lockAddressImtbl = import.meta.env.VUE_APP_LOCKER_ADDRESS const lockAddressMain = import.meta.env.VUE_APP_LOCKER_ADDRESS_MAIN export class Locker { constructor(_chainInstance) { this.bc = _chainInstance } async execLock(provider, lockAddress, nft, tokenIds) { const nftContract = new ethers.Contract(nft, erc721Abi, provider.getSigner()) const address = this.bc.store.passportAddress console.log('lock', nft, address, tokenIds) for (let tokenId of tokenIds) { const addressApproval = await nftContract.getApproved(tokenId) if ((addressApproval || "").toLowerCase() != lockAddress.toLowerCase()) { const resApproval = await nftContract.approve(lockAddress, tokenId); await provider.waitForTransaction(resApproval.hash) console.debug('approve', resApproval.hash) } } const contract = new ethers.Contract(lockAddress, lockAbi, provider.getSigner()) const res = await contract.lock(nft, address, tokenIds) await provider.waitForTransaction(res.hash) return res.hash } async lock(nft, tokenIds) { console.log('lock nft', nft, tokenIds) await this.bc.checkPassportLogin(); await this.bc.checkAndChangeChain(); return this.execLock(this.bc.web3Provider, lockAddressImtbl, nft, tokenIds) } async lockMain(nft, tokenIds) { console.log('lock nft on main', nft, tokenIds) const chainId = parseInt(import.meta.env.VUE_APP_NET_ID_MAIN); await this.bc.checkPassportLogin(); await this.bc.checkAndChangeChain(chainId, this.bc.eoaProvider); return this.execLock(this.bc.eoaProvider, lockAddressMain, nft, tokenIds) } async sendUnlockOrMint(provider, {from, to, data}) { const txHash = await provider.provider.request({ method: 'eth_sendTransaction', params: [{ from, to, data }] }) console.log(txHash) await provider.waitForTransaction(txHash) return txHash } async execUnlock(chainId, nft, tokenIds) { const preDatas = { net_id: chainId, contract_address: nft, tokens: tokenIds.map(token_id => {return { token_id }}), } const passportToken = await this.bc.passportToken() const { errcode, errmsg, trans_req } = await apiUnlockOrMint(preDatas, passportToken) if (errcode) { throw new Error(errmsg) } const web3Provider = this.bc.passportProvider || this.bc.web3Provider return this.sendUnlockOrMint(web3Provider, trans_req) } // imbtl上游戏内资产上链, 用于解锁或铸造 // 创世英雄, 普通英雄, 金砖 // 必须使用passport的provider async unlockOrMintGameNft(nft, tokenIds) { console.log('unlock nft', nft, tokenIds) await this.bc.checkPassportLogin(); await this.bc.checkAndChangeChain(); const chainId = import.meta.env.VUE_APP_NET_ID; return this.execUnlock(chainId, nft, tokenIds) } /** * Ethereum上解锁 * @param {*} nft * @param {*} tokenIds * @returns */ async unlockMain(nft, tokenIds) { console.log('unlock nft on main', nft, tokenIds) const chainId = parseInt(import.meta.env.VUE_APP_NET_ID_MAIN); await this.bc.checkPassportLogin(); await this.bc.checkAndChangeChain(chainId, this.bc.eoaProvider); return this.execUnlock(chainId, nft, tokenIds) } // 游戏内资产上链, 只用于mint // 该方法会显示一个确认弹窗, 由用户选择mint到哪个地址 async mintNft(tokenIds) { console.log('mint hero', tokenIds) const { provider, address } = await this.bc.selectAddress({}) const preDatas = { to: address, hero_uniids: tokenIds, } const passportToken = await this.bc.passportToken() const { errcode, errmsg, trans_req } = await apiMintNft(preDatas, passportToken) if (errcode) { throw new Error(errmsg) } trans_req.from = address return this.sendUnlockOrMint(this.bc.passportProvider, trans_req) } }