The Demo works, Connect your wallet to see it in action.
See demo folder in repository to see how its setup!
This Modal is copied from this Uniswap interface, as seen in the Uniswap exchange.
npm i vue3-web3modal
# or
yarn add vue3-web3modal
web3modal So you first have to install your desired providers;
//install desired providers
npm i Authereum
npm i Venly
npm i Portis
npm i Bitski
....
For all supported providers, see origninal web3modal providers for more info;
The providers options file format is the same as web3modal providers
// ./providerOptions.js
import Authereum from "authereum";
import { Venly } from "@venly/web3-provider";
import Portis from "@portis/web3";
import { Bitski } from "bitski";
export const providerOptions = {
walletconnect: {
package: WalletConnectProvider,
options: {
infuraId: process.env.VUE_APP_INFURA_KEY,
},
},
venly: {
package: Venly, // required
options: {
clientId: process.env.VUE_APP_VENLY_CLIENT_ID // required
}
},
portis: {
package: Portis, // required
options: {
id: process.env.VUE_APP_PORTIS_ID, // required
},
},
bitski: {
package: Bitski,
options: {
clientId: process.env.VUE_APP_BITSKI_CLIENT_ID,
callbackUrl: window.location.href + "bitski-callback.html",
},
},
Requires vue-i18n to be in your app
Some Providers dont support events so all transactions are confirmed using infura ;
infuraKey app key is required
// in your main.js
const infuraKey = process.env.VUE_APP_INFURA_KEY;
import {providerOptions} from './providers'
import { createApp } from 'vue';
import { createI18n } from "vue-i18n";
import { createWeb3 } from 'vue3-web3modal';
import App from './App.vue';
//To disable global registration , set global false
import { theme } from './theme';
import {providerOptions} from './providers'
const web3vue = createWeb3({
infuraKey,
providerOptions,
theme,
global:true // components will be registered globally
})
const app = createApp(App);
app.use(i18n);
app.use(web3vue);
app.config.devtools = true
app.mount('#app');
automatically registers the modal!
// import Web3Manager plugin and active web3
<script>
import { Web3Manager, useActiveWeb3Vue} from "vue3-web3modal";
export default {
components: {
Web3Manager,
},
setup() {
// all these variable need .value
const {
web3, //ref
account, //ref
etherBalance, //asyncComputed
chainId,//ref
providerInfo,//computed
isValidNetwork,//computed
active,//ref
error, //ref
} = useActiveWeb3Vue();
console.log(etherBalance.value)
return {
account
};
},
};
</script>
<template>
<Web3Manager />
</template>
The Web3Manager has a slot for user dropdown
<Web3Manager>
<UserDropDown>// your user dropdwon component
</Web3Manager>
First Disable automatic registration.
Automatic registration disabled by default In your main.js
const web3vue = createWeb3({
infuraKey,
providerOptions,
theme,
//global:true //remove this
})
In One of your Components eg App.vue
// import web menu plugin and activeweb3
<script>
import { Web3Modal, useActiveWeb3Vue, useWeb3ModalToggle} from "vue3-web3modal";
export default {
components: {
Web3Modal,
},
setup() {
// all these variable need .value
const {
web3, //ref
account, //ref
etherBalance, //asyncComputed
...
} = useActiveWeb3Vue();
console.log(etherBalance.value)
const { open, close, isOpen, toggle} = useWeb3ModalToggle();
return {
account,
toggle
};
},
};
</script>
<template>
<Web3Modal />
<a href="#" @click="toggle()">Connect Your Wallet</a>
</template>
Important!!! You must initialize and enable vue-i18n The Plugin uses vuei18n for translations .
{{$t('Connect Modal')}}
Add the following translations to your translation file: I will appreciate any pull requests for this ...
// in ./translations.js
const messages = {
en: {
"Account": "Account",
"Arbiscan": "Arbiscan",
"Arbitrum Bridge": "Arbitrum Bridge",
"Bridge": "Bridge",
"Bscscan": "Bscscan",
"Change": "Change",
"Check network status": "Check network status",
"close": "close",
"Connect": "Connect",
"Connect to a wallet": "Connect to a wallet",
"Connected with": "Connected with",
"Copied": "Copied",
"dashboard": "dashboard",
"Disconnect": "Disconnect",
"Error connecting": "Error connecting",
"Error Connecting": "Error Connecting",
"Error connecting. Try refreshing the page": "Error connecting. Try refreshing the page",
"Etherscan": "Etherscan",
"Help Center": "Help Center",
"here.": "here.",
"Initializing...": "Initializing...",
"Invalid Network": "Invalid Network",
"Network Warning": "Network Warning",
"onDismiss": "onDismiss",
"Optimism Gateway": "Optimism Gateway",
"Optimistic Etherscan": "Optimistic Etherscan",
"Pending": "Pending",
"Polygon Bridge": "Polygon Bridge",
"Polygonscan": "Polygonscan",
"Select a network": "Select a network",
"Show Portis": "Show Portis",
"Try Again ": "Try Again ",
"Wallet": "Wallet",
"Wrong Network": "Wrong Network",
"You may have lost your network connection, or {label} might be down right now.": "You may have lost your network connection, or {label} might be down right now.",
"You may have lost your network connection.": "You may have lost your network connection.",
"Your Wallets Network is not supported": "Your Wallets Network is not supported"
},
de:{
"Account": "Konto",
"Arbiscan": "Arbiscan",
....
//etc
}
}
Initialize vue-i18n
//in your main.js
.....
import translations from './messages'; // translations
// 2. Create i18n instance with options
const i18n = createI18n({
locale: 'en', // set locale
fallbackLocale: 'en', // set fallback locale
translations, // set locale messages
})
Place i18n before web3vue
const app = createApp(APP);
app.use(i18n); // translations come before
app.use(web3vue); // initialize web3vue
once the modal is enabled and permission granted by user you can access the following variable anywhere in your app
// anywhere in your app setup()
import { useActiveWeb3Vue } from "vue3-web3modal";
setup(){
const {
web3, //ref
account, //ref
etherBalance, //asyncComputed
chainId,//ref
providerInfo,//computed
isValidNetwork,//computed
active,//ref
error, //ref
} = useActiveWeb3Vue();
//example use of web3 initialized;
const contract = new web3.value.eth.Contract(your_toke_ABI, token_address);
const balance = await contract.methods.balanceOf(account.value);
console.log(web3.utils.fromWei(balance.toString()));
return{
account
web3
balance
}
}
web3
is null ref
before initialization
after its populated with the connected web3 account
import { useActiveWeb3Vue } from "vue3-web3modal";
/// in the component setup
setup(){
const { web3, account } = useActiveWeb3Vue();
const contract = new web3.value.eth.Contract(your_toke_ABI, token_address);
const balance = await contract.methods.balanceOf(account.value);
console.log(web3.utils.fromWei(balance.toString()));
return {
balance;
}
}
account
is a null
ref
before initialization
after user connected, is the users address;
It will be modified to new address if user changes address in wallet eg metamask
import { useActiveWeb3Vue } from "vue3-web3modal";
/// in the component setup
setup(){
const { account } = useActiveWeb3Vue();
console.log(account.value);
//0x7f0374480b9Ca09144F6cBd16774FDf1da1ae528
}
etherBalance
is a null
computed before initialization;
After user connected, is the users etherbalance in ETH;
Is computed
and will be recomputed if user changes network or address or spends or receives eth;
import { useActiveWeb3Vue } from "vue3-web3modal";
/// in the component setup
setup(){
const { etherBalance } = useActiveWeb3Vue();
console.log(etherBalance.value);
//0.054357546476767353
}
chainId
is a null ref
before initialization;
After user connected, is the users network chainId ;
Is a ref
and will be adjusted automatically if user changes network;
import { useActiveWeb3Vue } from "vue3-web3modal";
/// in the component setup
setup(){
const { chainId } = useActiveWeb3Vue();
console.log(chainId.value);
// 3
}
providerInfo
is the information of connected provider eg metamask , coinbase etc:
isValidNetwork
is a boolean
ref
, determines if user is connected to a supported network;
the follwoing networks are supported
MAINNET: 1,
ROPSTEN: 3,
RINKEBY: 4,
GOERLI: 5,
KOVAN: 42,
ARBITRUM_ONE: 42161,
ARBITRUM_RINKEBY: 421611,
OPTIMISM: 10,
OPTIMISTIC_KOVAN: 69,
POLYGON: 137,
POLYGON_MUMBAI: 80001,
BINANCE: 56,
BINANCE_TESTNET: 97,
usage
import { useActiveWeb3Vue } from "vue3-web3modal";
/// in the component setup
setup(){
const { isValidNetwork,providerInfo } = useActiveWeb3Vue();
if(isValidNetwork.value){
console(providerInfo.value)
/*{
name: metamask,
.....
}*/
}
// true
}
active
is a boolean
ref, determines if user the user has connected his wallet and everything is set;
error
is a ref
containing errors encountered,
you can use it to determine if everythiing is going ok
import { useActiveWeb3Vue } from "vue3-web3modal";
import {watch} from vue;
/// in the component setup
setup(){
const { active , error, web3 } = useActiveWeb3Vue();
watch([active, error], ([active, error])=>{
if(active){
login(); // user connected
}else{
logout() // user closed wallet
console.log('deactivated')
}
if(error){
showError(error);
}
})
}
Some providers dont support events, making it tough to confirm transactions. so to unify transactions confirmation, a method exists to confirm transactions via Infura
import { useActiveWeb3Vue, addTransaction, txBus } from "vue3-web3modal";
/// in the component setup
setup(){
const { web3 } = useActiveWeb3Vue();
const to = '0x7f0374480b9Ca09144F6cBd16774FDf1da1ae528';
const contract = new web3.value.eth.Contract(your_toke_ABI, token_address);
const amount = web3.utils.toWei('0.9675');
const hash = await contract.methods.transfer(to, amount);
// some providers dont support this
//contract.methods.transfer(to, amount).once('receipt',(receipt)=>console.log(receipt))
addTransaction({
hash,
onSuccess:(receipt)=>console.log(receipt), // after one confirmation
onError:(error)=>console.log(error), // called on any errors
summary:'Send 0.0967 ZBT', A summary Displayed to the user !!
approval: false, // flag to show tx is approval tx
})
// yoh can also listen to the tx's events on it hash
txBus.on(hash, ({receipt, error, hash, summary})=>{
// error occured if error was set;
if(error) return showError(error);
console.log(receipt.hash)
showNotification(summary.)
})
}
Again Some providers dont support events listening; You would be wise to use infura;
Infura doesnt support binance chain
import { useInfura } from "vue3-web3modal";
/// in the component setup
setup(){
//websocket with fallback to https;
const { infuraWss } = useInfura();
// infuraWss is a web3 instance connected to infura websockets
infuraWss.value.eth
.subscribe("newBlockHeaders")
.on("data", (block) => console.log(block));
// contracts events
const contract = new infuraWss.value.eth.Contract(your_toke_ABI, token_address);
contract.events.Transfer().on('data', (event)=> console.log(event))
}
By default, Uniswap colors are preserved, But we all have our themes Adjust the colours below to suit your needs.
I just extracted this theme in random, I dont what color goes where so experimemt and share
// in ./theme.js
import { computed, reactive } from "vue";
import { darkMode } from "vue3-web3modal";
export const theme = reactive({
colors: null,
// base
white:"#FFFFFF",
black:"#000000",
// text
text1: computed(() => darkMode.value ? "#FFFFFF" : "#000000"),
text2: computed(() => darkMode.value ? "#C3C5CB" : "#565A69"),
text3: computed(() => darkMode.value ? "#6C7284" : "#888D9B"),
text4: computed(() => darkMode.value ? "#565A69" : "#C3C5CB"),
// backgrounds / greys
// backgrounds / greys
bg0: computed(() => darkMode.value ? '#191B1F' : '#FFF'),
bg1: computed(() => darkMode.value ? '#212429' : '#F7F8FA'),
bg2: computed(() => darkMode.value ? '#2C2F36' : '#EDEEF2'),
bg3: computed(() => darkMode.value ? '#40444F' : '#CED0D9'),
bg4: computed(() => darkMode.value ? '#565A69' : '#888D9B'),
//borders
bd0: computed(() => darkMode.value ? '#191B1F' : '#CED0D9'),
bd1: computed(() => darkMode.value ? '#212429' : '#CED0D9'),
bd2: computed(() => darkMode.value ? '#2C2F36' : '#EDEEF2'),
bd3: computed(() => darkMode.value ? '#40444F' : '#CED0D9'),
//specialty colors
modalBG: computed(() => darkMode.value ? "rgba(0,0,0,.425)" : "rgba(0,0,0,0.3)"),
//primary colorsrgb(209 250 229)
primary1: computed(() => darkMode.value ? '#2172E5' : '#1e7e6b'),
//primary2: computed(() => darkMode.value ? '#3680E7' : '#78baad'),
primary3: computed(() => darkMode.value ? '#4D8FEA' : '#90c3b9'),
primary4: computed(() => darkMode.value ? '#376bad70' : '#a4d2c9'),
primary5: computed(() => darkMode.value ? '#153d6f70' : '#c2eae2'),
// color text
// color text
primaryText1: computed(() => darkMode.value ? '#5090ea' : '#1e7e6b'),
// other
red1: "#FD4040",
green1: "#27AE60",
yellow2: "#F3841E",
blue1: "#a78253",
//shadows
shadow1: computed(() => darkMode.value ? "#000" : "#2F80ED"),
});
add the theme to your main.js
// adjust your main.js
const infuraKey = process.env.VUE_APP_INFURA_KEY;
import { theme } from './theme'; // see theming below
import {providerOptions} from './providers' //we created this above
const web3vue = createWeb3({
infuraKey,
providerOptions,
theme, // add theme
})
const app = createApp(DemoApp);
app.use(i18n);
app.use(web3vue);
#Dark Mode
<script setup>
import { toggleDark, isDark } from "vue3-web3modal";
console.log(isDark);
</script>
<template>
<button @click="toggleDark()"> DarkMode </button>
</template>
if using vue-cli its recommeded to add your api keys to your .env
file;
in vue-cli the VUE_APP_
prefix ie required
// in ./.env -->these are dummies
VUE_APP_INFURA_KEY=7cd6581wth84a5e9084450a8c9a90e8j
VUE_APP_FORTMATIC_KEY=pk_live_5CYC964AFEDW4B62
VUE_APP_PORTIS_ID=01801ec8-5ec5-4070-aeff-4a955ea4bccb
....
// const infuraKey = process.env.VUE_APP_INFURA_KEY;
Or Laravel
The MIX_
prefix is required
// in ./.env
MIX_INFURA_KEY=7cd6581wth84a5e9084450a8c9a90e8j
MIX_FORTMATIC_KEY=pk_live_5CYC964AFEDW4B62
MIX_PORTIS_ID=01801ec8-5ec5-4070-aeff-4a955ea4bccb
....
- Fork it!
- Create your feature branch:
git checkout -b my-new-feature
- Commit your changes:
git commit -am 'Add some feature'
- Push to the branch:
git push origin my-new-feature
- Submit a pull request :D
vue3-web3modal © envatic, Released under the MIT License.
Authored and maintained by envatic with help from contributors (list).