VueJS对接WalletConnect含源码

Posted 新缸中之脑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VueJS对接WalletConnect含源码相关的知识,希望对你有一定的参考价值。

在本文中,我们将使用 WalletConnect 将钱包应用链接到我们使用Vue.js开发的去中心化应用。

去中心化应用程序 (DApps) 的主要功能之一是能够连接钱包,这反过来又允许用户与 DApp 上的交易进行交互。它抽象了诸如交换网络、提供签名者和其他为用户提供身份验证形式的功能等功能。连接钱包还充当网关,允许用户通过 DApp 使用他们的钱包地址作为授权身份在区块链上进行和读取操作。

WalletConnect是一个免费的开源协议,可以将我们的 DApp 连接到多个钱包,包括MetaMask、Trust Wallet、Rainbow 等。该协议通过在 DApp 和钱包之间建立连接来抽象这个过程,使它们在整个会话期间保持同步。

你可以在此处下载本教程的源代码,应用程序的演示请访问这里

用熟悉的语言学习 Web3.0开发Java | Php | Python | .Net / C# | Golang | Node.JS | Flutter / Dart

1、Vue.js 应用程序开发

首先,让我们使用 Vue CLI 启动项目。如果你的系统上已经安装了 Vue CLI,可以继续直接创建 Vue 项目。

可以使用以下命令全局安装它:

npm install -g @vue / cli

我们现在可以使用 Vue CLI 来创建我们的项目。使用以下命令创建一个新项目:

vue create vue-wallet-connect

你将需要选择一个预设。选择,然后选择如下所示的选项:Manually select features

创建项目后,导航到新的项目文件夹:

cd vue-wallet-connect

我们将在Vue 应用程序中使用Ethers.js在连接钱包时直接与区块链交互:

npm i ethers

在这里,我们将 WalletConnect 库安装到项目中:

npm install --save web3 @walletconnect/web3-provider

接下来,要直接在 Vue 3 中使用 WalletConnect 库,我们需要安装node-polyfill-webpack-plugin

npm i node-polyfill-webpack-plugin

我们安装这个插件是因为项目使用 webpack v5,其中删除了 polyfill Node 核心模块。因此,需要安装它以访问项目中的这些模块。

现在,打开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",
      ,
    ,
  ,
);

完成后,现在可以启动服务器:

npm run serve

2、构建用户界面

让我们进入 components 文件夹并创建一个名为StatusContainer.vue的文件, 该组件包含我们的主页。

这个文件包含了欢迎信息、帮助我们连接的Connect Wallet按钮以及用于断开我们与钱包的连接的Disconnect按钮。最后,当我们成功连接到钱包时,会显示Connected按钮:

<template>
  <div class="hello">
    <h1>Welcome to Your Vue.js Dapp</h1>
    <div >
       <button class="button">Connected</button>
       <button class="disconnect__button">Disconnect</button>
    </div>

    <button class="button"> Connect Wallet</button>
  </div>
</template>
<script>
export default 
  name: 'StatusContainer'

</script>

完成后,打开App.vue文件并导入StatusContainer组件,如下所示:

<template>
  <status-container/>
</template>
<script>

import StatusContainer from './components/StatusContainer.vue'
export default 
  name: 'App',
  components: 
    StatusContainer
  

</script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Sora:wght@100&display=swap');
#app 
  font-family: 'Sora', sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;

.button 
      background-color: #1c82ff;
    border: none;
    color: #ffffff;
    font-family: "Sora";
    border-radius: 3rem;
    padding: 2rem 3rem;
    font-weight: 600;
    font-size: 2rem;
    margin: 1rem 1rem 1rem auto;
    width: 40%;

.disconnect__button 
     background-color: red;
    border: none;
    color: #ffffff;
    font-family: "Sora";
    border-radius: 3rem;
    padding: 1rem 1.3rem;
    font-weight: 600;
    font-size: 1rem;
    margin: 8rem 1rem 1rem auto;
    width: 20%;

</style>

在样式标签中,现在为之前创建的按钮添加样式:.button.disconnect。 此外,我们从 Google Fonts 导入 Sora Custom Font 并在.__buttonfont-family样式中使用该字体。

3、实例化 WalletConnect

我们将需要一个 RPC 提供程序来实例化 WalletConnect 库。对于此示例,我们将使用Infura

打开 Infura,创建一个新项目,然后获取项目 ID。

现在,在 src/walletConnect 文件夹下创建一个新文件夹walletConnect, 在这个文件夹中,让我们创建一个文件provider.js。在这里,我们导入 WalletConnect 库,并使用我们的 Infura ID 对其进行实例化,然后将其导出以用于其他文件。

src/walletConnect/provider.js看起来像这样:

import WalletConnectProvider from "@walletconnect/web3-provider";
export const provider = new WalletConnectProvider(
  infuraId: process.env.VUE_APP_INFURA_ID,
);

Infura ID 应当设置为环境变量。因此,将以下内容添加到你的.env文件中:

VUE_APP_INFURA_ID=INFURA__ID

4、创建Composables

在创建接口并成功实例化我们的库之后,下一步是实现功能。为此,我们将使用 Vue composables,因为它允许我们在应用程序的任何组件中使用我们的状态和操作,类似于Pinia和 Vuex。

在src文件夹内,添加src/composables/connect,在connect文件夹中,让我们创建一个index.js文件。

在这里,我们导入reactivewatch,我们将在这个文件中使用它。让我们创建状态对象defaultState

import  reactive, watch  from "vue";

const defaultState = 
  address: "",
  chainId: "",
  status: false,
;

const state = defaultState

为了保持状态一致,我们将状态与本地存储中的项目同步。让我们命名这个条目为userState并将其分配给一个名为STATE_NAME 的变量。这样做是为了避免userState在多个地方重复时出错:

const STATE_NAME = "userState";

我们使用watch来监听状态的任何变化,以便及时更新本地存储:

watch(
  () => state,
  () => 
    localStorage.setItem(STATE_NAME, JSON.stringify(state));
  ,
   deep: true 
);

接下来,我们创建一个getDefaultState函数来检查本地存储中的STATE_NAME项是否存在,并将本地存储项赋给状态。如果本地存储项不存在,它会将defaultState赋给state

现在,我们可以删除const state = defaultState并使用reactive来赋值:

const getDefaultState = () => 
  if (localStorage.getItem(STATE_NAME) !== null) 
    return JSON.parse(localStorage.getItem(STATE_NAME));
  
  return defaultState;
;
const state = reactive(getDefaultState());

最后,我们导出状态。我们还添加了一条if语句来检查本地存储项是否不存在。如果没有,它会创建项目并分配state给本地存储:

 export default () => 
  if (localStorage.getItem(STATE_NAME) === null) 
    localStorage.setItem(STATE_NAME, JSON.stringify(state));
  
  return 
    state,
  ;
;

现在,我们的状态总是与本地存储同步,确保一致性。

让我们看看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,
  ;
;

5、创建Actions

Actions由将在程序中使用的功能组成。我们将创建三个函数:

  • connectWalletConnect,这会触发 WalletConnect 与钱包连接
  • autoConnect,它在 DApp 连接后处理我们 WalletConnect 会话中的一致性,因此当 DApp 连接并且刷新页面后,用户的会话仍然处于活动状态
  • disconnectWallet,这会断开 DApp 与钱包的连接并结束用户的会话

让我们直接进入代码!

仍在我们的src/composables/connect文件夹中,创建connectWalletConnect文件。首先,我们导入index文件等:

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;

然后我们用provider监听三个事件: disconnect、accountsChanged和chainChainged。

  • disconnect:一旦用户直接从他们的钱包断开连接就会触发
  • accountsChanged:如果用户在其钱包中切换帐户,则会触发。如果account数组的长度大于零,我们将state.address设置为数组第一个地址,也就是当前地址
  • chainChainged:如果用户切换其链/网络,则会触发。例如,如果从以太坊主网切换到 rinkeby 测试网,我们的应用程序会将state.chainId从1更改为4。

然后,我们的catch语句只是将任何错误记录到控制台。

返回到connect文件夹中的index.js文件并导入connectWalletConnect动作。在这里,我们创建一个actions对象并使用state导出:

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,
  ;
;

6、实现组件逻辑

让我们打开StatusContainer组件并将composables中的逻辑连接到接口。像往常一样,导入文件并对其进行解构以获取动作和状态:

<script>
import connect from '../composables/connect/index';
export default 
  name: 'StatusContainer',
  setup: () => 
    const  connectWalletConnect, disconnectWallet, state  = connect();
    const connectUserWallet = async () => 
      await connectWalletConnect();
    ;

    const disconnectUser = async() => 
      await disconnectWallet()
    
    return 
      connectUserWallet,
      disconnectUser,
      state
    
  

</script>

然后返回函数 ( disconnectUser, connectUserWallet) 和state以便在模板中使用:

<template>
  <div class="hello">
    <h1>Welcome to Your Vue.js Dapp</h1>
    <div v-if="state.status">
       <button  @click="connectUserWallet" class="button">Connected</button>
       <h3>Address: state.address</h3>
       <h3>ChainId: state.chainId</h3>
       <button  @click="disconnectUser" class="disconnect__button">Disconnect</button>
    </div>

    <button v-else @click="connectUserWallet" class="button"> Connect Wallet</button>
  </div>
</template>

首先,我们用v-if来有条件地显示事物,使用state.status。 如果已连接并且state.status为真,我们将显示Connected按钮、用户addresschainId。此外,我们将显示一个触发disconnectUser功能的断开连接按钮。

如果用户没有连接并且state.statusfalse,我们只显示触发connectUserWallet功能的连接钱包按钮。

7、结束语

在本文中,我们介绍了在 Vue DApp 中集成 WalletConnect 的详细步骤。内容涵盖项目配置、界面构建、逻辑编写、状态同步等环节,以确保我们的应用程序始终与钱包同步。


原文链接:Vue.js对接WalletConnect教程 — 汇智网

以上是关于VueJS对接WalletConnect含源码的主要内容,如果未能解决你的问题,请参考以下文章

在 ReactJS 中集成时出现 WalletConnect 错误 - Uncaught (in promise) TypeError: this.send is not a function

通信基于matlab语音信号仿真含Matlab源码 957期

如何在 Vuejs+Webpack 中包含外部 sass 目录?

如何在 vuejs 组件中包含 js 文件?

图像分割基于matlab遗传算法优化K聚类图像分割含Matlab源码 1605期

天下支付ecshop,thinkphp,shopnc在线支付接口,支付插件(payment plugin含源码)