Wagmi
Wagmi enables application developers to focus on building high-quality, high-performance experiences for Ethereum by prioritizing developer experience, performance, feature coverage, and stability. It provides developers with intuitive building blocks to create their Ethereum applications.
This section will introduce how to integrate Bitget Wallet
and Bitget Wallet Lite
into the Wagmi system.
Quick Start
1.Install Dependencies
js
pnpm add wagmi
pnpm add wagmi
2.Configuring chains and providers
js
import { configureChains, allChains } from "wagmi";
import { alchemyProvider } from "wagmi/providers/alchemy";
import { publicProvider } from "wagmi/providers/public";
// Configure chains & providers with the Alchemy provider.
// Two popular providers are Alchemy (alchemy.com) and Infura (infura.io)
const { chains, provider } = configureChains(allChains, [
alchemyProvider(),
publicProvider(),
]);
import { configureChains, allChains } from "wagmi";
import { alchemyProvider } from "wagmi/providers/alchemy";
import { publicProvider } from "wagmi/providers/public";
// Configure chains & providers with the Alchemy provider.
// Two popular providers are Alchemy (alchemy.com) and Infura (infura.io)
const { chains, provider } = configureChains(allChains, [
alchemyProvider(),
publicProvider(),
]);
3.create BitgetWalletConnector
js
import { InjectedConnector } from "wagmi/connectors/injected";
class BitgetWalletConnector extends InjectedConnector {
constructor({ chains = [], options_ = {} }) {
const options = {
name: "BitgetWallet",
...options_,
};
super({ chains, options });
this.id = "BitgetWallet";
this.ready =
typeof window != "undefined" &&
!!this.findProvider(window?.bitkeep?.ethereum);
}
async getProvider() {
if (typeof window !== "undefined") {
// TODO: Fallback to `ethereum#initialized` event for async injection
// https://github.com/BitKeep/detect-provider#synchronous-and-asynchronous-injection=
this.provider = window.bitkeep?.ethereum;
}
return this.provider;
}
getReady(ethereum) {
if (!ethereum.isBitKeep || !ethereum) return;
// Brave tries to make itself look like BitKeep
// Could also try RPC `web3_clientVersion` if following is unreliable
if (ethereum.isBraveWallet && !ethereum._events && !ethereum._state) return;
if (ethereum.isTokenPocket) return;
if (ethereum.isTokenary) return;
return ethereum;
}
findProvider(ethereum) {
if (ethereum?.providers) return ethereum.providers.find(this.getReady);
return this.getReady(ethereum);
}
}
import { InjectedConnector } from "wagmi/connectors/injected";
class BitgetWalletConnector extends InjectedConnector {
constructor({ chains = [], options_ = {} }) {
const options = {
name: "BitgetWallet",
...options_,
};
super({ chains, options });
this.id = "BitgetWallet";
this.ready =
typeof window != "undefined" &&
!!this.findProvider(window?.bitkeep?.ethereum);
}
async getProvider() {
if (typeof window !== "undefined") {
// TODO: Fallback to `ethereum#initialized` event for async injection
// https://github.com/BitKeep/detect-provider#synchronous-and-asynchronous-injection=
this.provider = window.bitkeep?.ethereum;
}
return this.provider;
}
getReady(ethereum) {
if (!ethereum.isBitKeep || !ethereum) return;
// Brave tries to make itself look like BitKeep
// Could also try RPC `web3_clientVersion` if following is unreliable
if (ethereum.isBraveWallet && !ethereum._events && !ethereum._state) return;
if (ethereum.isTokenPocket) return;
if (ethereum.isTokenary) return;
return ethereum;
}
findProvider(ethereum) {
if (ethereum?.providers) return ethereum.providers.find(this.getReady);
return this.getReady(ethereum);
}
}
4.Create BitgetWalletLiteConnector
js
import { InjectedConnector } from "wagmi/connectors/injected";
import {
OmniConnect
} from "@bitget-wallet/omni-connect";
class BitgetWalletLiteConnector extends InjectedConnector {
constructor({ chains = [], options_ = {} }) {
const options = {
name: "BitgetWallet",
...options_,
};
super({ chains, options });
this.id = "BitgetWallet";
this.ready =
typeof window != "undefined" &&
!!this.findProvider(window?.bitkeep?.ethereum);
this.omni = new OmniConnect({
metadata: {
name: options_.dappName,
iconUrl: options_.dappIconUrl,
url: options_.dappUrl,
privacyPolicyUrl: "",
termsOfUseUrl: "",
},
namespace: {
eip155: {
chains: chains,
// methods: ["eth_sign", "personal_sign"],
// events: ["accountsChanged", "chainChanged"],
},
},
});
}
async getProvider() {
if (typeof window !== "undefined") {
// TODO: Fallback to `ethereum#initialized` event for async injection
// https://github.com/BitKeep/detect-provider#synchronous-and-asynchronous-injection=
this.provider = this.omni?.eip155?.provider
}
return this.provider;
}
getReady(ethereum) {
if (!ethereum.isBitKeep || !ethereum) return;
// Brave tries to make itself look like BitKeep
// Could also try RPC `web3_clientVersion` if following is unreliable
if (ethereum.isBraveWallet && !ethereum._events && !ethereum._state) return;
if (ethereum.isTokenPocket) return;
if (ethereum.isTokenary) return;
return ethereum;
}
findProvider(ethereum) {
if (ethereum?.providers) return ethereum.providers.find(this.getReady);
return this.getReady(ethereum);
}
}
import { InjectedConnector } from "wagmi/connectors/injected";
import {
OmniConnect
} from "@bitget-wallet/omni-connect";
class BitgetWalletLiteConnector extends InjectedConnector {
constructor({ chains = [], options_ = {} }) {
const options = {
name: "BitgetWallet",
...options_,
};
super({ chains, options });
this.id = "BitgetWallet";
this.ready =
typeof window != "undefined" &&
!!this.findProvider(window?.bitkeep?.ethereum);
this.omni = new OmniConnect({
metadata: {
name: options_.dappName,
iconUrl: options_.dappIconUrl,
url: options_.dappUrl,
privacyPolicyUrl: "",
termsOfUseUrl: "",
},
namespace: {
eip155: {
chains: chains,
// methods: ["eth_sign", "personal_sign"],
// events: ["accountsChanged", "chainChanged"],
},
},
});
}
async getProvider() {
if (typeof window !== "undefined") {
// TODO: Fallback to `ethereum#initialized` event for async injection
// https://github.com/BitKeep/detect-provider#synchronous-and-asynchronous-injection=
this.provider = this.omni?.eip155?.provider
}
return this.provider;
}
getReady(ethereum) {
if (!ethereum.isBitKeep || !ethereum) return;
// Brave tries to make itself look like BitKeep
// Could also try RPC `web3_clientVersion` if following is unreliable
if (ethereum.isBraveWallet && !ethereum._events && !ethereum._state) return;
if (ethereum.isTokenPocket) return;
if (ethereum.isTokenary) return;
return ethereum;
}
findProvider(ethereum) {
if (ethereum?.providers) return ethereum.providers.find(this.getReady);
return this.getReady(ethereum);
}
}
5.Set client
js
import { createClient } from "wagmi";
import { MetaMaskConnector } from "wagmi/connectors/metaMask";
import BitgetWalletConnector from "./connectors/BitgetWalletConnector";
const mainnetIds = [1, 10, 137, 42161]; // BitgetWallet only supports the mainnet network for the time being
// Set up client
const client = createClient({
autoConnect: true,
connectors: [
new MetaMaskConnector({ chains }),
new BitgetWalletConnector({
chains: chains.filter((v) => mainnetIds.includes(v.id)),
options: {
name: "BitgetWallet",
icon: "./assets/bitkeep-icon.png",
},
}),
new BitgetWalletConnector({
chains: chains.filter((v) => mainnetIds.includes(v.id)),
options: {
name: "BitgetWallet",
iconUrl: "./assets/bitkeep-icon.png",
dappName:'your dappName',
dappIconUrl:'your dappIconUrl',
dappUrl:'your dappUrl',
},
}),
],
provider,
});
import { createClient } from "wagmi";
import { MetaMaskConnector } from "wagmi/connectors/metaMask";
import BitgetWalletConnector from "./connectors/BitgetWalletConnector";
const mainnetIds = [1, 10, 137, 42161]; // BitgetWallet only supports the mainnet network for the time being
// Set up client
const client = createClient({
autoConnect: true,
connectors: [
new MetaMaskConnector({ chains }),
new BitgetWalletConnector({
chains: chains.filter((v) => mainnetIds.includes(v.id)),
options: {
name: "BitgetWallet",
icon: "./assets/bitkeep-icon.png",
},
}),
new BitgetWalletConnector({
chains: chains.filter((v) => mainnetIds.includes(v.id)),
options: {
name: "BitgetWallet",
iconUrl: "./assets/bitkeep-icon.png",
dappName:'your dappName',
dappIconUrl:'your dappIconUrl',
dappUrl:'your dappUrl',
},
}),
],
provider,
});
Use in React App
jsx
import {
WagmiConfig,
useConnect,
useAccount,
useDisconnect,
useSignMessage,
useNetwork,
useSwitchNetwork,
} from "wagmi";
import { verifyMessage } from "ethers/lib/utils";
const { isConnected, connector } = useAccount();
const { connect, connectors, error, isLoading, pendingConnector } =
useConnect();
const { disconnect } = useDisconnect();
export function NetworkSwitcher() {
const { chain } = useNetwork();
const { chains, error, isLoading, pendingChainId, switchNetwork } =
useSwitchNetwork();
if (!chain) return null;
return (
<div>
<div>
Connected to {chain?.name ?? chain?.id}
{chain?.unsupported && " (unsupported)"}
</div>
{switchNetwork && (
<div>
{chains.map((x) =>
x.id === chain?.id ? null : (
<button key={x.id} onClick={() => switchNetwork(x.id)}>
{x.name}
{isLoading && x.id === pendingChainId && " (switching)"}
</button>
)
)}
</div>
)}
<div>{error && error.message}</div>
</div>
);
}
function SignMessage() {
const recoveredAddress = React.useRef();
const { data, error, isLoading, signMessage } = useSignMessage({
onSuccess(data, variables) {
// Verify signature when sign message succeeds
const address = verifyMessage(variables.message, data);
recoveredAddress.current = address;
},
});
return (
<form
onSubmit={(event) => {
event.preventDefault();
const formData = new FormData(event.target);
const message = formData.get("message");
signMessage({ message });
}}
>
<label htmlFor="message">Enter a message to sign</label>
<textarea
id="message"
name="message"
placeholder="The quick brown fox…"
/>
<button disabled={isLoading}>
{isLoading ? "Check Wallet" : "Sign Message"}
</button>
{data && (
<div>
<div>Recovered Address: {recoveredAddress.current}</div>
<div>Signature: {data}</div>
</div>
)}
{error && <div>{error.message}</div>}
</form>
);
}
export function Profile() {
const { isConnected, connector } = useAccount();
const { connect, connectors, error, isLoading, pendingConnector } =
useConnect();
const { disconnect } = useDisconnect();
return (
<div>
<div className="block">
{isConnected && (
<button onClick={() => disconnect()}>
Disconnect from {connector?.name}
</button>
)}
{connectors.map((connector) => (
<button
disabled={!connector.ready}
key={connector.id}
onClick={() => connect({ connector })}
>
<img src={connector.icon}></img>
{connector.name}
{!connector.ready && " (unsupported)"}
{isLoading &&
connector.id === pendingConnector?.id &&
" (connecting)"}
</button>
))}
{error && <div>{error.message}</div>}
</div>
<div className="block">
<Account></Account>
</div>
<div className="block">
<NetworkSwitcher></NetworkSwitcher>
</div>
{isConnected && (
<div className="block">
<SignMessage />
</div>
)}
</div>
);
}
function App() {
return (
<div className="App">
<WagmiConfig client={client}>
<Profile />
</WagmiConfig>
</div>
);
}
import {
WagmiConfig,
useConnect,
useAccount,
useDisconnect,
useSignMessage,
useNetwork,
useSwitchNetwork,
} from "wagmi";
import { verifyMessage } from "ethers/lib/utils";
const { isConnected, connector } = useAccount();
const { connect, connectors, error, isLoading, pendingConnector } =
useConnect();
const { disconnect } = useDisconnect();
export function NetworkSwitcher() {
const { chain } = useNetwork();
const { chains, error, isLoading, pendingChainId, switchNetwork } =
useSwitchNetwork();
if (!chain) return null;
return (
<div>
<div>
Connected to {chain?.name ?? chain?.id}
{chain?.unsupported && " (unsupported)"}
</div>
{switchNetwork && (
<div>
{chains.map((x) =>
x.id === chain?.id ? null : (
<button key={x.id} onClick={() => switchNetwork(x.id)}>
{x.name}
{isLoading && x.id === pendingChainId && " (switching)"}
</button>
)
)}
</div>
)}
<div>{error && error.message}</div>
</div>
);
}
function SignMessage() {
const recoveredAddress = React.useRef();
const { data, error, isLoading, signMessage } = useSignMessage({
onSuccess(data, variables) {
// Verify signature when sign message succeeds
const address = verifyMessage(variables.message, data);
recoveredAddress.current = address;
},
});
return (
<form
onSubmit={(event) => {
event.preventDefault();
const formData = new FormData(event.target);
const message = formData.get("message");
signMessage({ message });
}}
>
<label htmlFor="message">Enter a message to sign</label>
<textarea
id="message"
name="message"
placeholder="The quick brown fox…"
/>
<button disabled={isLoading}>
{isLoading ? "Check Wallet" : "Sign Message"}
</button>
{data && (
<div>
<div>Recovered Address: {recoveredAddress.current}</div>
<div>Signature: {data}</div>
</div>
)}
{error && <div>{error.message}</div>}
</form>
);
}
export function Profile() {
const { isConnected, connector } = useAccount();
const { connect, connectors, error, isLoading, pendingConnector } =
useConnect();
const { disconnect } = useDisconnect();
return (
<div>
<div className="block">
{isConnected && (
<button onClick={() => disconnect()}>
Disconnect from {connector?.name}
</button>
)}
{connectors.map((connector) => (
<button
disabled={!connector.ready}
key={connector.id}
onClick={() => connect({ connector })}
>
<img src={connector.icon}></img>
{connector.name}
{!connector.ready && " (unsupported)"}
{isLoading &&
connector.id === pendingConnector?.id &&
" (connecting)"}
</button>
))}
{error && <div>{error.message}</div>}
</div>
<div className="block">
<Account></Account>
</div>
<div className="block">
<NetworkSwitcher></NetworkSwitcher>
</div>
{isConnected && (
<div className="block">
<SignMessage />
</div>
)}
</div>
);
}
function App() {
return (
<div className="App">
<WagmiConfig client={client}>
<Profile />
</WagmiConfig>
</div>
);
}