Decentralized applications (DApps) are transforming how users interact with blockchain technology, offering secure, non-custodial access to digital assets and services. One of the most critical features of any DApp is wallet connectivity—this allows users to authenticate, sign transactions, switch networks, and securely engage with smart contracts using their preferred crypto wallet.
WalletConnect is a free, open-source protocol that enables seamless communication between DApps and wallets like MetaMask, Trust Wallet, and Rainbow. By establishing an encrypted bridge between your Vue.js frontend and a user’s mobile or browser wallet, WalletConnect enhances both security and usability.
In this guide, you’ll learn how to integrate WalletConnect into a Vue.js DApp step by step. We'll cover project setup, UI creation, state management using Vue composables, and implementing core wallet actions such as connect, auto-reconnect, and disconnect—all while ensuring session persistence and real-time updates.
Whether you're building on Ethereum, Polygon, or another EVM-compatible chain, this integration pattern works universally across custodial and non-custodial wallets that support WalletConnect.
Setting Up Your Vue.js Project
To begin, ensure you have the Vue CLI installed globally:
npm install -g @vue/cliNext, create a new Vue project:
vue create vue-wallet-connectWhen prompted, select Manually select features, then include Babel and Vue Router (optional). Once created, navigate into the project directory:
cd vue-wallet-connectNow install the required dependencies:
npm install ethers @walletconnect/web3-provider web3 node-polyfill-webpack-pluginNote: Webpack 5 no longer includes Node.js polyfills by default. The node-polyfill-webpack-plugin restores these for compatibility with libraries like WalletConnect.Update your vue.config.js file with the following configuration:
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",
},
},
},
});Start the development server:
npm run serveYou now have a fully functional Vue.js environment ready for blockchain integration.
👉 Discover how easy it is to start interacting with blockchain wallets today.
Building the User Interface
Create a new component at src/components/StatusContainer.vue. This will serve as the main interface for connecting and displaying wallet status.
<template>
<div>
<h1>Welcome to Your Vue.js DApp</h1>
<div v-if="state.status" class="connected-section">
<p>Connected</p>
<p>Address: {{ state.address }}</p>
<p>ChainId: {{ state.chainId }}</p>
<button @click="disconnectUser" class="disconnect__button">Disconnect</button>
</div>
<button v-else @click="connectUserWallet" class="button">Connect Wallet</button>
</div>
</template>
<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>In App.vue, import and register the component:
<template>
<StatusContainer />
</template>
<script>
import StatusContainer from './components/StatusContainer.vue';
import connect from './composables/connect/index';
import { onMounted } from 'vue';
export default {
name: 'App',
components: { StatusContainer },
setup() {
const { autoConnect } = connect();
onMounted(async () => {
await autoConnect();
});
}
};
</script>Add styling in <style> tags using Google Fonts for a clean look:
@import url('https://fonts.googleapis.com/css2?family=Sora:wght@100&display=swap');
#app {
font-family: 'Sora', sans-serif;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.button {
background-color: #1c82ff;
border: none;
color: white;
font-family: "Sora";
border-radius: 3rem;
padding: 2rem 3rem;
font-weight: 600;
font-size: 2rem;
width: 40%;
}
.disconnect__button {
background-color: red;
color: white;
font-family: "Sora";
border-radius: 3rem;
padding: 1rem 1.3rem;
font-size: 1rem;
width: 20%;
}Configuring WalletConnect Provider
To establish a connection, you need an RPC provider. We’ll use Infura—a reliable node service for Ethereum and other chains.
- Sign up at infura.io
- Create a new project and copy your Project ID
- Store it securely in a
.envfile:
VUE_APP_INFURA_ID=your_infura_project_id_hereCreate src/walletConnect/provider.js:
import WalletConnectProvider from "@walletconnect/web3-provider";
export const provider = new WalletConnectProvider({
infuraId: process.env.VUE_APP_INFURA_ID,
});This exports a configured WalletConnect provider instance that your app will use to initiate connections.
Managing State with Vue Composables
Vue 3’s Composition API allows us to abstract logic into reusable composables. We’ll create one to manage wallet state—address, chain ID, and connection status—with persistence via localStorage.
Create src/composables/connect/index.js:
import { reactive, watch } from "vue";
import connectWalletConnect from "./connectWalletConnect";
import autoConnect from "./autoConnect";
import disconnectWallet from "./disconnectWallet";
const defaultState = {
address: "",
chainId: "",
status: false,
};
const STATE_NAME = "userState";
const getDefaultState = () => {
const saved = localStorage.getItem(STATE_NAME);
return saved ? JSON.parse(saved) : defaultState;
};
const state = reactive(getDefaultState());
watch(
() => state,
() => {
localStorage.setItem(STATE_NAME, JSON.stringify(state));
},
{ deep: true }
);
const actions = {
connectWalletConnect,
autoConnect,
disconnectWallet,
};
export default () => {
if (!localStorage.getItem(STATE_NAME)) {
localStorage.setItem(STATE_NAME, JSON.stringify(state));
}
return { state, ...actions };
};This composable ensures state remains consistent across page reloads.
Implementing Core Wallet Actions
Connect Wallet Functionality
Create src/composables/connect/connectWalletConnect.js:
import { providers } from "ethers";
import connect from "./index";
import { provider } from "../../walletConnect/provider";
const connectWalletConnect = async () => {
try {
const { state } = connect();
await provider.enable();
const web3Provider = new providers.Web3Provider(provider);
const signer = await web3Provider.getSigner();
const address = await signer.getAddress();
state.address = address;
state.chainId = await provider.request({ method: "eth_chainId" });
state.status = true;
provider.on("disconnect", () => {
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.error("Connection failed:", error);
}
};
export default connectWalletConnect;This function triggers the QR code modal and listens for key events.
Auto-Reconnect on Page Load
Create src/composables/connect/autoConnect.js:
import connect from "./index";
const autoConnect = () => {
const { state, connectWalletConnect } = connect();
if (state.status && !localStorage.getItem("walletconnect")) {
state.status = false;
state.address = "";
localStorage.removeItem("userState");
}
if (localStorage.getItem("walletconnect")) {
(async () => await connectWalletConnect())();
}
};
export default autoConnect;This restores the session if a valid WalletConnect session exists.
Disconnect Wallet
Create src/composables/connect/disconnectWallet.js:
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;Frequently Asked Questions
Q: Can I use WalletConnect with any blockchain?
A: Yes—WalletConnect supports all EVM-compatible chains including Ethereum, BSC, Polygon, Arbitrum, and more. Just ensure your Infura or RPC endpoint supports the target network.
Q: Why do I need node-polyfill-webpack-plugin?
A: Webpack v5 removed built-in Node.js polyfills. Libraries like WalletConnect depend on them, so this plugin restores compatibility without manual configuration.
Q: Is user data stored on servers when using WalletConnect?
A: No. WalletConnect uses end-to-end encryption via a relay server. Private keys never leave the user’s device, and no personal data is collected.
Q: How does auto-connect work after page refresh?
A: When connected, WalletConnect stores session data in localStorage. Our autoConnect function checks this data on load and re-establishes the provider connection if valid.
Q: What happens if the user switches networks in their wallet?
A: The chainChanged event listener automatically updates the state.chainId, allowing your DApp to respond instantly—ideal for multi-chain applications.
👉 See how top DApps handle secure wallet integration effortlessly.
Finalizing Integration
With all components in place—UI, composable logic, event handling, and persistent state—you now have a fully functional WalletConnect-powered Vue.js DApp.
Users can scan a QR code to connect securely, perform transactions via their preferred wallet, and enjoy uninterrupted sessions even after refreshing the page. All interactions remain non-custodial and privacy-preserving.
This foundation can be extended to support features like token balances, NFT display, transaction history, or cross-chain swaps—making it ideal for DeFi dashboards, NFT marketplaces, or Web3 social platforms.
Whether you're a beginner exploring blockchain development or a seasoned engineer building production-grade DApps, integrating WalletConnect with Vue.js offers a robust starting point.
👉 Start building powerful Web3 experiences with modern tools.