新聞中心
去中心化應(yīng)用程序(DApps)的主要功能之一是連接錢包的能力,這反過來又允許用戶與DApp上的交易互動(dòng)。它抽象了一些功能,如切換網(wǎng)絡(luò),提供簽名者,以及其他為用戶提供一種認(rèn)證形式的功能。連接錢包也作為一個(gè)網(wǎng)關(guān),允許用戶通過DApp在區(qū)塊鏈上進(jìn)行和讀取操作,使用他們的錢包地址作為授權(quán)身份。

我們提供的服務(wù)有:網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站制作、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、同江ssl等。為成百上千企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的同江網(wǎng)站制作公司
WalletConnect是一個(gè)免費(fèi)的開源協(xié)議,使我們的DApp與多個(gè)錢包連接成為可能,包括MetaMask、Trust Wallet、Rainbow和其他錢包。該協(xié)議通過在DApp和錢包之間建立連接來抽象這個(gè)過程,使它們在整個(gè)會(huì)話中保持同步。
在這篇文章中,我們將使用WalletConnect將我們的錢包應(yīng)用與我們的DApp連接起來,在前端使用Vue.js。需要注意的是,WalletConnect可以用在任何兼容WalletConnect的DApp、鏈和錢包(托管和非托管)上。
你可以在這里找到本教程的源代碼,以及我們將建立的應(yīng)用程序的演示。
開始使用Vue.js應(yīng)用程序
首先,讓我們使用Vue CLI來啟動(dòng)這個(gè)項(xiàng)目。如果你的系統(tǒng)中已經(jīng)安裝了Vue CLI,你可以直接創(chuàng)建Vue項(xiàng)目。
你可以用這個(gè)命令全局安裝它。
npm install -g @vue/cli
現(xiàn)在我們可以使用Vue CLI來創(chuàng)建我們的項(xiàng)目。用這個(gè)命令創(chuàng)建一個(gè)新項(xiàng)目。
vue create vue-wallet-connect
你將需要挑選一個(gè)預(yù)設(shè)。選擇手動(dòng)選擇功能,然后選擇如下所示的選項(xiàng)。
在項(xiàng)目被創(chuàng)建后,導(dǎo)航到新的項(xiàng)目文件夾。
cd vue-wallet-connect
我們將在我們的Vue應(yīng)用程序中使用Ethers.js,在連接我們的錢包時(shí)直接與區(qū)塊鏈互動(dòng)。
npm i ethers
在這里,我們將WalletConnect庫安裝到你的項(xiàng)目中。
npm install --save web3 @walletconnect/web3-provider
接下來,為了在Vue 3中直接使用WalletConnect庫,我們需要安裝node-polyfill-webpack-plugin。
npm i node-polyfill-webpack-plugin
我們安裝它是因?yàn)槲覀兊捻?xiàng)目使用webpack v5,其中polyfill Node核心模塊被刪除。所以,我們安裝它是為了在項(xiàng)目中訪問這些模塊。
現(xiàn)在,打開vue.config.js文件,用這段代碼替換它。
const { defineConfig } = require("@vue/cli-service");
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");
module.exports = defineConfig({
transpileDependencies: true,
configureWebpack: {
plugins: [new NodePolyfillPlugin()],
optimization: {
splitChunks: {
chunks: "all",
},
},
},
});一旦完成,你就可以啟動(dòng)服務(wù)器了。
npm run serve
構(gòu)建用戶界面
讓我們進(jìn)入組件文件夾,創(chuàng)建一個(gè)名為StatusContainer.vue的新文件。這個(gè)組件包含我們的主頁面。
它有我們的歡迎詞,幫助我們連接的連接錢包按鈕,以及斷開我們與錢包連接的斷開按鈕。最后,當(dāng)我們成功連接到一個(gè)錢包時(shí),顯示Connected按鈕。
Welcome to Your Vue.js Dapp
一旦完成,打開App.vue文件,像這樣導(dǎo)入StatusContainer組件。
在我們的樣式標(biāo)簽中,我們現(xiàn)在為我們先前創(chuàng)建的按鈕添加樣式:.button和.disconnect__button。另外,我們從Google Fonts導(dǎo)入Sora自定義字體,并將其作為我們的字體家族。
實(shí)例化WalletConnect
我們將需要一個(gè)RPC提供者來實(shí)例化我們的WalletConnect庫。在這個(gè)例子中,我們將使用Infura。打開Infura,創(chuàng)建一個(gè)新的項(xiàng)目,并獲取項(xiàng)目ID。
現(xiàn)在,在src文件夾下創(chuàng)建一個(gè)新的walletConnect文件夾:src/walletConnect。在這個(gè)文件夾中,讓我們創(chuàng)建一個(gè)provider.js文件。在這里,我們導(dǎo)入我們的WalletConnect庫,使用我們的Infura ID將其實(shí)例化,并導(dǎo)出它以便在其他文件中使用。
src/walletConnect/provider.js將看起來像這樣。
import WalletConnectProvider from "@walletconnect/web3-provider";
export const provider = new WalletConnectProvider({
infuraId: process.env.VUE_APP_INFURA_ID,
});
Infura的ID應(yīng)該作為環(huán)境變量使用。所以在你的.env文件中添加以下內(nèi)容。
VUE_APP_INFURA_ID={{INFURA__ID}}使用可合成物添加功能
在創(chuàng)建我們的接口并成功實(shí)例化我們的庫之后,下一步是實(shí)現(xiàn)我們的功能。為了做到這一點(diǎn),我們將使用Vue composables,因?yàn)樗试S我們在應(yīng)用中的任何組件中使用我們的狀態(tài)和動(dòng)作,類似于我們在Pinea和Vuex中的情況。
創(chuàng)建一個(gè)可組合的
在src文件夾內(nèi),添加src/composables/connect。在connect文件夾內(nèi),讓我們創(chuàng)建一個(gè)index.js文件。
在這里,我們導(dǎo)入reactive和watch,我們將在這個(gè)文件中使用它們。讓我們創(chuàng)建一個(gè)叫做defaultState的狀態(tài)對象。
import { reactive, watch } from "vue";
const defaultState = {
address: "",
chainId: "",
status: false,
};
const state = defaultState為了保持狀態(tài)的一致性,我們將狀態(tài)與本地存儲(chǔ)中的一個(gè)項(xiàng)目進(jìn)行同步。讓我們把這個(gè)項(xiàng)目命名為 "userState",并把它分配給一個(gè)叫做STATE_NAME的變量。這樣做是為了避免在多個(gè)地方重復(fù) "userState "時(shí)犯錯(cuò)誤。
const STATE_NAME = "userState";
現(xiàn)在我們使用watch來更新我們的本地存儲(chǔ),一旦我們的狀態(tài)有任何變化。
watch(
() state,
() {
localStorage.setItem(STATE_NAME, JSON.stringify(state));
},
{ deep: true }
);
接下來,我們創(chuàng)建一個(gè)getDefaultState函數(shù),檢查我們本地存儲(chǔ)中的STATE_NAME項(xiàng)是否存在,并將本地存儲(chǔ)項(xiàng)分配給狀態(tài)。如果我們的本地存儲(chǔ)項(xiàng)不存在,它就將默認(rèn)狀態(tài)分配給state。
現(xiàn)在,我們可以刪除 const state = defaultState 并使用 reactive 來分配 const state = reactive(getDefaultState());。
const getDefaultState = () {
if (localStorage.getItem(STATE_NAME) !== null) {
return JSON.parse(localStorage.getItem(STATE_NAME));
}
return defaultState;
};
const state = reactive(getDefaultState());最后,我們導(dǎo)出我們的狀態(tài)。我們還添加了一個(gè)if語句,檢查我們的本地存儲(chǔ)項(xiàng)是否不存在。如果不存在,它就創(chuàng)建這個(gè)項(xiàng)目并將狀態(tài)分配給本地存儲(chǔ)。
export default () => {
if (localStorage.getItem(STATE_NAME) === null) {
localStorage.setItem(STATE_NAME, JSON.stringify(state));
}
return {
state,
};
};現(xiàn)在,我們的狀態(tài)總是與本地存儲(chǔ)同步,確保一致性。
我們來看看 src/composables/connect/index.js。
import { reactive, watch } from "vue";
const defaultState = {
address: "",
chainId: "",
status: false,
};
const STATE_NAME = "userState";
const getDefaultState = () {
if (localStorage.getItem(STATE_NAME) !== null) {
return JSON.parse(localStorage.getItem(STATE_NAME));
}
return defaultState;
};
const state = reactive(getDefaultState());
watch(
() state,
() {
localStorage.setItem(STATE_NAME, JSON.stringify(state));
},
{ deep: true }
);
export default () => {
if (localStorage.getItem(STATE_NAME) === null) {
localStorage.setItem(STATE_NAME, JSON.stringify(state));
}
return {
state,
};
};創(chuàng)建動(dòng)作
我們的動(dòng)作由將在我們的應(yīng)用程序中使用的函數(shù)組成。我們將創(chuàng)建三個(gè)函數(shù)。
- ? connectWalletConnect,用于觸發(fā)WalletConnect模式以連接錢包
- ? autoConnect,在DApp連接后處理WalletConnect會(huì)話的一致性,所以當(dāng)DApp連接后,你刷新頁面時(shí),用戶的會(huì)話仍然是活動(dòng)的。
- ? disconnectWallet,斷開DApp與錢包的連接并結(jié)束用戶的會(huì)話。
讓我們直接跳到代碼中
ConnectWalletConnect
還是在我們的connect文件夾(src/composables/connect)中,創(chuàng)建connectWalletConnect文件。首先,我們導(dǎo)入我們的索引文件,來自以太坊的提供者,以及我們之前在 src/walletConnect/provider.js 文件中創(chuàng)建的提供者。
import { providers } from "ethers";
import connect from "./index";
import { provider } from "../../walletConnect/provider";
const connectWalletConnect = async () => {
try {
const { state } = connect();
// Enable session (triggers QR Code modal)
await provider.enable();
const web3Provider = new providers.Web3Provider(provider);
const signer = await web3Provider.getSigner();
const address = await signer.getAddress();
state.status = true;
state.address = address;
state.chainId = await provider.request({ method: "eth_chainId" });
provider.on("disconnect", (code, reason) => {
console.log(code, reason);
console.log("disconnected");
state.status = false;
state.address = "";
localStorage.removeItem("userState");
});
provider.on("accountsChanged", (accounts) => {
if (accounts.length > 0) {
state.address = accounts[0];
}
});
provider.on("chainChanged", (chainId) => {
state.chainId = chainId
});
} catch (error) {
console.log(error);
}
};
export default connectWalletConnect;接下來,我們有一個(gè)try-catch語句。在我們的嘗試語句中,我們從connect()中獲得我們的狀態(tài),并彈出我們的QR模式進(jìn)行連接。一旦連接,我們就將我們的地址和chainId分配給狀態(tài)屬性,并使我們的state.status讀作true。
然后,我們用提供者觀察三個(gè)事件:斷開連接、賬戶變更和鏈?zhǔn)竭B接。
- ? 一旦用戶直接從他們的錢包斷開連接,就會(huì)觸發(fā)斷開連接。
- ? accountsChanged是在用戶切換他們錢包中的賬戶時(shí)觸發(fā)的。如果賬戶數(shù)組的長度大于0,我們將state.address分配給數(shù)組中的第一個(gè)地址(accounts[0]),也就是當(dāng)前地址。
- ? 如果用戶切換了他們的鏈/網(wǎng)絡(luò),就會(huì)觸發(fā) chainChainged。例如,如果他們將他們的鏈從Ethereum mainnet切換到rinkeby testnet,我們的應(yīng)用程序?qū)tate.chainId從1變?yōu)?。
然后,我們的catch語句只是將任何錯(cuò)誤記錄到控制臺(tái)。
回到connect文件夾中的index.js文件,導(dǎo)入connectWalletConnect動(dòng)作。在這里,我們創(chuàng)建一個(gè)動(dòng)作對象,并將其與我們的狀態(tài)一起導(dǎo)出。
import { reactive, watch } from "vue";
import connectWalletConnect from "./connectWalletConnect";
const STATE_NAME = "userState";
const defaultState = {
address: "",
chainId: "",
status: false,
};
const getDefaultState = () {
if (localStorage.getItem(STATE_NAME) !== null) {
return JSON.parse(localStorage.getItem(STATE_NAME));
}
return defaultState;
};
const state = reactive(getDefaultState());
const actions = {
connectWalletConnect,
};
watch(
() state,
() {
localStorage.setItem(STATE_NAME, JSON.stringify(state));
},
{ deep: true }
);
export default () => {
if (localStorage.getItem(STATE_NAME) === null) {
localStorage.setItem(STATE_NAME, JSON.stringify(state));
}
return {
state,
...actions,
};
};autoConnect
讓我們繼續(xù)看autoConnect.js,以及我們的動(dòng)作。與 connectWalletConnect 類似,創(chuàng)建一個(gè) autoConnect.js 文件。我們導(dǎo)入索引文件并對其進(jìn)行解構(gòu),以獲得我們的狀態(tài),并使用connect()進(jìn)行connectWalletConnect。
import connect from "./index";
const autoConnect = () {
const { state, connectWalletConnect } = connect();
if (state.status) {
if (localStorage.getItem("walletconnect") == null) {
console.log("disconnected");
console.log("disconnected");
state.status = false;
state.address = "";
localStorage.removeItem("userState");
}
if (localStorage.getItem("walletconnect")) {
(async () => {
console.log("start");
connectWalletConnect();
})();
}
}
};
export default autoConnect;
你應(yīng)該知道的一件事是,一旦WalletConnect成功連接到一個(gè)DApp,所有關(guān)于該錢包的信息(包括地址和鏈ID)都在本地存儲(chǔ)中,在一個(gè)名為walletconnect的項(xiàng)目下。一旦會(huì)話被斷開,它就會(huì)被自動(dòng)刪除。
autoConnect檢查我們的state.status是否為true。如果是,我們就檢查本地存儲(chǔ)中是否有一個(gè)walletConnect項(xiàng)目。如果它不在本地存儲(chǔ)中,我們就刪除我們的狀態(tài)中的所有現(xiàn)有數(shù)據(jù)和本地存儲(chǔ)中的userState項(xiàng)。
然而,如果walletconnect存在于你的本地存儲(chǔ)中,我們有一個(gè)異步函數(shù),通過啟動(dòng)connectWalletConnect();為我們的DApp "重新激活 "現(xiàn)有會(huì)話。因此,如果我們刷新頁面,連接仍然是活躍的,并且可以監(jiān)聽我們的提供者事件。
斷開錢包
讓我們來看看最后一個(gè)動(dòng)作:disconnectWallet。這個(gè)動(dòng)作允許我們從DApp本身結(jié)束會(huì)話。
首先,我們導(dǎo)入我們的提供者和狀態(tài)。然后,我們使用provider.disconnect();來斷開會(huì)話,之后我們將狀態(tài)重置為默認(rèn)值,并刪除本地存儲(chǔ)中的 "userState "項(xiàng)目。
import { provider } from "../../walletConnect/provider";
import connect from "./index";
const disconnectWallet = async () => {
const { state } = connect();
await provider.disconnect();
state.status = false;
state.address = "";
localStorage.removeItem("userState");
}
export default disconnectWallet;現(xiàn)在我們可以回到我們的src/composables/connect/index.js中,像這樣更新動(dòng)作對象。
const actions = {
connectWalletConnect,
autoConnect,
disconnectWallet
};在我們的組件中實(shí)現(xiàn)邏輯
讓我們打開我們的StatusContainer組件,將我們的可組合文件中的邏輯連接到接口上。像往常一樣,導(dǎo)入你的可組合文件并對其進(jìn)行解構(gòu),以獲得動(dòng)作(連接和斷開)和我們的狀態(tài)。
然后我們返回函數(shù)(disconnectUser,connectUserWallet)和狀態(tài),以便在模板中使用。
Welcome to Your Vue.js Dapp
Address: {{state.address}}
ChainId: {{state.chainId}}
首先,我們使用v-if來有條件地顯示東西,使用state.status。如果我們連接了并且state.status為真,我們就會(huì)顯示Connected按鈕、用戶地址和chainId。同時(shí),我們會(huì)顯示一個(gè)斷開連接的按鈕,觸發(fā)我們的disconnectUser函數(shù)。
如果用戶沒有連接,且state.status為false,我們只顯示連接錢包按鈕,點(diǎn)擊后會(huì)觸發(fā)我們的connectUserWallet函數(shù)。
添加自動(dòng)連接
讓我們進(jìn)入App.vue組件,將自動(dòng)連接邏輯添加到該組件中。與我們之前所做的類似,我們導(dǎo)入我們的composable,并對其進(jìn)行解構(gòu)以獲得autoConnect動(dòng)作。使用Vue的onMounted,我們將啟動(dòng)autoConnect()函數(shù)。如前所述,這使我們能夠監(jiān)聽來自錢包的實(shí)時(shí)事件,即使我們刷新頁面。
結(jié)論
如果你一路走到這里,那就恭喜你了!
在這篇文章中,我們介紹了在你的Vue DApps中實(shí)現(xiàn)WalletConnect的逐步細(xì)節(jié)。從用正確的配置設(shè)置我們的項(xiàng)目和構(gòu)建我們的界面,到編寫必要的邏輯以確保我們的應(yīng)用程序始終與錢包保持同步。
當(dāng)前標(biāo)題:將WalletConnect集成到Vue.jsDApps中
文章轉(zhuǎn)載:http://m.fisionsoft.com.cn/article/dpoigoe.html


咨詢
建站咨詢
