WalletConnect
Bitget mobile wallet now supports WalletConnect.
WalletConnect is an open protocol that connects wallets and DApps (Web3 applications). It uses a bridge server to establish a remote connection between two applications and/or devices, allowing them to scan a QR code to establish the connection and start communication.
- Chains officially supported by WalletConnect: Cosmos, Ethereum, Solana, Near, StarkNet More: WalletConnect Multi-Chain
- Bitget Wallet now supports: Ethereum, Cosmos
Integration steps
- Register and activate WalletConnect service
- Install WalletConnect SDK on the frontend
- Parameter configuration and initialization
- Wallet app QR code verification
Development Example
js
import WalletConnect from '@walletconnect/client';
import QRCodeModal from '@walletconnect/qrcode-modal';
class WalletConnectQrcodeDemo extends React.Component {
connector = null;
state = {
connector: null,
connected: false,
chainId: 1,
selectedAddress: "",
};
connect = async () => {
// bridge url
const bridge = "https://bridge.walletconnect.org";
// create new connector
const connector = new WalletConnect({ bridge, qrcodeModal: QRCodeModal });
// check if already connected
if (!connector.connected) {
// create new session
await connector.createSession();
} else {
const { chainId, accounts } = connector;
this.setState({
selectedAddress: accounts[0],
chainId: chainId,
});
}
this.connector = connector;
// subscribe to events
await this.initEvent();
};
initEvent() {
this.connector.on("connect", (error, payload) => {
console.log(`connector.on("connect")`);
alert("connected");
if (error) {
throw error;
}
// Get provided accounts and chainId
const { accounts, chainId } = payload.params[0];
this.setState({
selectedAddress: accounts[0],
chainId: chainId,
});
});
this.connector.on("session_update", (error, payload) => {
console.log(`connector.on("session_update")`);
alert("session_update");
if (error) {
throw error;
}
const { accounts, chainId } = payload.params[0];
this.setState({
selectedAddress: accounts[0],
chainId: chainId,
});
});
this.connector.on("disconnect", (error, payload) => {
console.log(`connector.on("disconnect")`);
alert("disconnect");
if (error) {
throw error;
}
this.setState({
selectedAddress: "",
chainId: 1,
});
});
}
disconnected() {
if (this.connector) {
this.connector.killSession();
this.setState({
selectedAddress: "",
chainId: 1,
});
}
}
async sendTransaction() {
// Draft transaction
const tx = {
from: this.state.selectedAddress, // Required
to: document.querySelector("#to").value, // Required (for non contract deployments)
data: "0x", // Required
gasPrice: "0x02540be400", // Optional
gas: "0x9c40", // Optional
value: String(document.querySelector("#amount").value * 10 ** Number(18)), // Optional
// nonce: "0x0114", // Optional
};
// Send transaction
return this.connector.sendTransaction(tx);
}
render() {
const { selectedAddress, chainId } = this.state;
return (
<>
<div className="testdemo">
<div>
<h1>connect</h1>
{<button disabled={selectedAddress} data-method="connect" onClick={this.connect.bind(this)}>connect</button>}
{<button data-method="disconnected" onClick={this.disconnected.bind(this)}>disconnected</button>}
<div>
selectedAddress: <span id="account">{selectedAddress}</span>
</div>
<div>
chainId : <span id="chainId">{chainId}</span>
</div>
</div>
<div>
<h1>transfer EVM</h1>
from:
<input id="from" type="text" value={selectedAddress} disabled/>
to:
<input id="to" type="text" value="0x1da770d53eBe21c79cebD9cb0C9ce885BeD251DC"/>
amount:
<input id="amount" type="number" />
<button data-method="sendTransaction" onClick={this.sendTransaction.bind(this)}>sendTranstion</button>
</div>
</div>
</>
);
}
}
import WalletConnect from '@walletconnect/client';
import QRCodeModal from '@walletconnect/qrcode-modal';
class WalletConnectQrcodeDemo extends React.Component {
connector = null;
state = {
connector: null,
connected: false,
chainId: 1,
selectedAddress: "",
};
connect = async () => {
// bridge url
const bridge = "https://bridge.walletconnect.org";
// create new connector
const connector = new WalletConnect({ bridge, qrcodeModal: QRCodeModal });
// check if already connected
if (!connector.connected) {
// create new session
await connector.createSession();
} else {
const { chainId, accounts } = connector;
this.setState({
selectedAddress: accounts[0],
chainId: chainId,
});
}
this.connector = connector;
// subscribe to events
await this.initEvent();
};
initEvent() {
this.connector.on("connect", (error, payload) => {
console.log(`connector.on("connect")`);
alert("connected");
if (error) {
throw error;
}
// Get provided accounts and chainId
const { accounts, chainId } = payload.params[0];
this.setState({
selectedAddress: accounts[0],
chainId: chainId,
});
});
this.connector.on("session_update", (error, payload) => {
console.log(`connector.on("session_update")`);
alert("session_update");
if (error) {
throw error;
}
const { accounts, chainId } = payload.params[0];
this.setState({
selectedAddress: accounts[0],
chainId: chainId,
});
});
this.connector.on("disconnect", (error, payload) => {
console.log(`connector.on("disconnect")`);
alert("disconnect");
if (error) {
throw error;
}
this.setState({
selectedAddress: "",
chainId: 1,
});
});
}
disconnected() {
if (this.connector) {
this.connector.killSession();
this.setState({
selectedAddress: "",
chainId: 1,
});
}
}
async sendTransaction() {
// Draft transaction
const tx = {
from: this.state.selectedAddress, // Required
to: document.querySelector("#to").value, // Required (for non contract deployments)
data: "0x", // Required
gasPrice: "0x02540be400", // Optional
gas: "0x9c40", // Optional
value: String(document.querySelector("#amount").value * 10 ** Number(18)), // Optional
// nonce: "0x0114", // Optional
};
// Send transaction
return this.connector.sendTransaction(tx);
}
render() {
const { selectedAddress, chainId } = this.state;
return (
<>
<div className="testdemo">
<div>
<h1>connect</h1>
{<button disabled={selectedAddress} data-method="connect" onClick={this.connect.bind(this)}>connect</button>}
{<button data-method="disconnected" onClick={this.disconnected.bind(this)}>disconnected</button>}
<div>
selectedAddress: <span id="account">{selectedAddress}</span>
</div>
<div>
chainId : <span id="chainId">{chainId}</span>
</div>
</div>
<div>
<h1>transfer EVM</h1>
from:
<input id="from" type="text" value={selectedAddress} disabled/>
to:
<input id="to" type="text" value="0x1da770d53eBe21c79cebD9cb0C9ce885BeD251DC"/>
amount:
<input id="amount" type="number" />
<button data-method="sendTransaction" onClick={this.sendTransaction.bind(this)}>sendTranstion</button>
</div>
</div>
</>
);
}
}
Custom Configuration of Wallet Information
js
import { createWeb3Modal, defaultConfig } from "@web3modal/ethers/react";
// 1. Get projectId
const projectId = "YOUR_PROJECT_ID";
// 2. Set chains
const mainnet = {
chainId: 1,
name: "Ethereum",
currency: "ETH",
explorerUrl: "https://etherscan.io",
rpcUrl: "https://cloudflare-eth.com",
};
// 3. Create a metadata object
const metadata = {
name: "My Website",
description: "My Website description",
url: "https://mywebsite.com", // origin must match your domain & subdomain
icons: ["https://avatars.mywebsite.com/"],
};
// 4. Create Ethers config
const ethersConfig = defaultConfig({
/*Required*/
metadata,
/*Optional*/
enableEIP6963: true, // true by default
enableInjected: true, // true by default
enableCoinbase: true, // true by default
rpcUrl: "...", // used for the Coinbase SDK
defaultChainId: 1, // used for the Coinbase SDK
});
// 5. Create a Web3Modal instance
createWeb3Modal({
ethersConfig,
chains: [mainnet],
projectId,
enableAnalytics: true, // Optional - defaults to your Cloud configuration
featuredWalletIds: [
//Select wallets that are going to be shown on the modal's main view. Default wallets are MetaMask and Trust Wallet. Array of wallet ids defined will be prioritized (order is respected). These wallets will also show up first in All Wallets view. You can find the wallets ids in https://explorer.walletconnect.com/?type=wallet
"id1",
"id2",
"...",
],
});
export default function App() {
return <YourApp />;
}
import { createWeb3Modal, defaultConfig } from "@web3modal/ethers/react";
// 1. Get projectId
const projectId = "YOUR_PROJECT_ID";
// 2. Set chains
const mainnet = {
chainId: 1,
name: "Ethereum",
currency: "ETH",
explorerUrl: "https://etherscan.io",
rpcUrl: "https://cloudflare-eth.com",
};
// 3. Create a metadata object
const metadata = {
name: "My Website",
description: "My Website description",
url: "https://mywebsite.com", // origin must match your domain & subdomain
icons: ["https://avatars.mywebsite.com/"],
};
// 4. Create Ethers config
const ethersConfig = defaultConfig({
/*Required*/
metadata,
/*Optional*/
enableEIP6963: true, // true by default
enableInjected: true, // true by default
enableCoinbase: true, // true by default
rpcUrl: "...", // used for the Coinbase SDK
defaultChainId: 1, // used for the Coinbase SDK
});
// 5. Create a Web3Modal instance
createWeb3Modal({
ethersConfig,
chains: [mainnet],
projectId,
enableAnalytics: true, // Optional - defaults to your Cloud configuration
featuredWalletIds: [
//Select wallets that are going to be shown on the modal's main view. Default wallets are MetaMask and Trust Wallet. Array of wallet ids defined will be prioritized (order is respected). These wallets will also show up first in All Wallets view. You can find the wallets ids in https://explorer.walletconnect.com/?type=wallet
"id1",
"id2",
"...",
],
});
export default function App() {
return <YourApp />;
}
*Bug Related to featuredWalletIds Configuration:featuredWalletIds option is broken, starting from v4.2.2
Further reading
- WalletConnect Official Development Documentation https://docs.walletconnect.com
- WalletConnect Official Examples https://github.com/WalletConnect/web-examples