这段时间学了vue3的setup语法糖和pinia这个新的状态管理工具,并且最近都在和web3打交道,
就这样搞了个web3的封装,这比用vue2的时候只能用mixins混入来封装来的舒服多了
(用mixins很难判断自己的代码,真的很混乱)
使用之前请使用Chrome浏览器并且下载安装MetaMask钱包
创建src/utils/loadElement.js
import { ElLoading, ElMessage } from 'element-plus'
export const lockLoadHandler = (text) => {
return ElLoading.service({
lock: true,
text: text,
// spinner: LoadSvg,
background: 'rgba(0, 0, 0, 0.7)',
})
}
export const PlusElMessage = (option) => {
return ElMessage({
duration: option.type == 'error'? 0 : 3000,
grouping: true,
showClose: true,
...option
})
}
创建src/hooks/useWeb3.js
import Web3 from 'web3'; import { lockLoadHandler, PlusElMessage } from "@/utils/loadElement"; import { /*引入合约*/ } from '@/abis/abis.js'; function getEth() { if (typeof window.ethereum === "undefined") { const message = 'MetaMask not installed' //没安装MetaMask钱包进行弹框提示 PlusElMessage({ type: 'error', message // '请安装MetaMask' }) throw new Error('MetaMask not installed'); } else { if (process.env.NODE_ENV == 'production' && window.ethereum.chainId != '0x38') { const message = 'MetaMask currently in an informal network' PlusElMessage({ type: 'error', message // 'MetaMask 处于非正式网络中' }) throw new Error(message); } else { return window.ethereum } } } export async function useWeb3(callback) { const loadHandler = lockLoadHandler('正在获取授权...') try { const web3Provider = await getEth() const userAddress = await web3Provider.enable();//hte enable function will be removed // const userAddress = await web3Provider.request({ method: 'eth_requestAccounts' }); const web3 = new Web3(web3Provider); loadHandler.close(); callback && callback(web3, userAddress[0]) web3Provider && web3Provider.on("accountsChanged", function (accounts) { console.log('用户切换了钱包', accounts[0]);//一旦切换账号这里就会执行 callback && callback(web3, accounts[0]) }); return web3 } catch (error) { console.error(error) const message = 'User denied account access' PlusElMessage({ type: 'error', message // '请安装MetaMask' }) loadHandler.close() throw new Error(message); } } export function getContract(web3, abi, abiAddress) { return new web3.eth.Contract(abi, abiAddress) } export async function startContracts(web3) { const 合约名 = await getContract(web3, 合约json, 合约链接); return { 合约名 } } export async function getUserAddress(_web3) { let userAddress = ''; await _web3.eth.getAccounts().then(res=> userAddress = res[0]); return userAddress; }
创建src/stores/web3js.js
import { defineStore } from "pinia";
import { useWeb3, startContracts } from "@/hooks/useWeb3"
export const UseStoreWeb3js = defineStore('Web3js', {
state: () => ({
_web3: null,
_address: '',
}),
getters: {
web3: ({ _web3 }) => _web3,
haveAuth: ({ _web3 }) => !!_web3,//是否被授权
userAddress: ({ _address }) => _address,
fromWei: ({ _web3 }) => {
let fromWei;
if (_web3.utils) {
fromWei = _web3.utils.fromWei;
}
return fromWei;
}
},
actions: {
async startWeb3() {
const web3InCode = await useWeb3(async (web3Eth, userAddress) => {
// console.log('用户切换了钱包后的操作')
this.setUserAddress(userAddress)
this.setWeb3(web3Eth)
const { setContracts } = UseStoreContracts();
const contracts = await startContracts(web3Eth);
setContracts(contracts);
})
return !!web3InCode
},
setWeb3(web3) {
this._web3 = web3
},
setUserAddress(address) {
this._address = address
}
}
})
export const UseStoreContracts = defineStore('contracts', {
state: () => ({
_Contracts: null,
}),
getters: {
Contracts: ({ _Contracts }) => _Contracts,
},
actions: {
setContracts(Contracts) {
// console.log('Contracts set **---',Contracts)
this._Contracts = Contracts
},
}
})
在需要用到的地方使用,最好是在app或者layout级别的组件中,这样就不必每次都去请求响应。
<script setup>
import {
UseStoreWeb3js,
} from "@/stores/web3js"
const useStoreWeb3js = UseStoreWeb3js();
const { haveAuth, startWeb3 } = useStoreWeb3js;
if (!haveAuth) {
console.log('获取web3')
startWeb3();
}
</script>
如果是在vuerouter路由守卫中
import { createRouter, createWebHashHistory } from 'vue-router';
import routes from "./routes.js";
import { UseStoreWeb3js } from '@/stores/web3js.js';
const router = createRouter({
routes,
history: createWebHashHistory(),
});
const whitePathList = [
'/',
'/home',
]
router.beforeEach(async (to, from, next) => {
const storeWeb3 = UseStoreWeb3js();
const { startWeb3, haveAuth } = storeWeb3;
console.log("router beforeEach", to.path)
//验证是否被赋予权限
if (!haveAuth && !whitePathList.includes(to.path)) {
//没有就去请求
try {
console.log('try startWeb3')
const queryWeb3 = await startWeb3();
if (queryWeb3) {
next(to.path)
} else {
next('/home');
}
} catch (error) {
console.error(error)
next('/home');
}
} else {
next();
}
})
router.afterEach((to) => {
document.title = to.meta.title
})
export default router
好了,基本上就是这样链接上web3的钱包,至于合约的细节则自行搜索web3区块链之类的技术吧。
这里是海星吧,我们下次见。
拜拜*V*