This guide is intended for developers looking to integrate BitKeep wallet functions for various use cases. But if you are a user who is looking to experience the various features of Bitget Wallet (previously BitKeep), then head over to https://docs.bitkeep.com/guide/wallet/quickly.html.
Bitget is a decentralized multi-chain digital wallet, dedicated to providing safe and convenient one-stop digital asset management services to users around the world. Bitget supports Mantle Network and other 30+ chains like Ethereum and Optimism.
Before we begin, please use the link below for updated testnet and mainnet addresses.
https://docs.mantle.xyz/network/for-devs/developing-on-mantle#network-details
What’s the easiest way to connect to Bitget Wallet
Check if the provider is window.bitkeep.ethereum
. If not, please replace it with the exclusive Bitget provider window.bitkeep.ethereum
.
For example, see below:
function getProvider() {
const provider = window.bitkeep && window.bitkeep.ethereum;
if (!provider) {
return window.open('https://bitkeep.com/en/download?type=2');
}
return provider;
}
Attention ⚠️: In case of multiple plug-in wallets installed, you need to remove listeners to avoid conflicts. Otherwise, the user may not be able to switch different plug-in wallets. Clicking on Bitget can only invoke MetaMask or other wallets with the same specification with an error message.
For example, see below:
//Bitkeep used
const BitKeepProvider = window.bitkeep && window.bitkeep.ethereum;
await BitKeepProvider.request({ method: 'eth_requestAccounts' });
BitKeepProvider.removeAllListeners();
BitKeepProvider.on('accountsChanged', async (accounts) => {
console.log("accounts changed")
});
BitKeepProvider.on('chainChanged', async (chainId) => {
console.log("chainId changed")
});
//MetaMask used
const MetaMaskProvider = window.ethereum;
//BitKeepProvider.removeAllListeners();
MetaMaskProvider.request({ method: 'eth_requestAccounts' });
MetaMaskProvider.removeAllListeners();
MetaMaskProvider.on('accountsChanged', async (accounts) => {
console.log("accounts changed")
});
MetaMaskProvider.on('chainChanged', async (chainId) => {
console.log("chainId changed")
});
Basic Usage
For any non-trivial Ethereum web application — a.k.a. dApp, web3 sites, etc. — to work, you will have to:
- Detect the Ethereum provider (
window?.bitkeep?.ethereum
) - Detect which Ethereum network the user is connected to
- Get the user's Ethereum account(s)
You can refer to eth-requestaccounts or address-conflicts-when-switching-network code snippet
The provider API is all you need to create a full-featured web3 application.
You can refer a third-party base about Web3.0 login to support Bitget Wallet quickly, such as:
//npm install bitkeep-web3modal
// fork from https://github.com/WalletConnect/web3modal https://github.com/WalletConnect/web3modal/issues/574
import web3modal from 'bitkeep-web3modal';
const web3Modal = new Web3Modal({
network: 'mainnet', // optional
cacheProvider: true, // optional
providerOptions: {
bitkeep: {
package: true,
},
walletconnect: {
display: {
logo: 'data:image/gif;base64,INSERT_BASE64_STRING',
name: 'Mobile',
description: 'Scan qrcode with your mobile wallet',
},
package: WalletConnectProvider,
options: {
infuraId: 'INFURA_ID', // required
},
},
}, // required
});
isConnected()
Note: Note that this method has nothing to do with the user's accounts. You may often encounter the word "connected" in reference to whether a web3 site can access the user's accounts. In the provider interface, however, "connected" and "disconnected" refer to whether the provider can make RPC requests to the current chain.
const Provider = getProvider();
Provider.isConnected();
request(args)
const Provider = getProvider();
interface RequestArguments {
method: string;
params?: unknown[] | object;
}
Provider.request(args: RequestArguments): Promise<unknown>;
Supported Methods
- eth_requestAccounts
- wallet_watchAsset
- wallet_switchEthereumChain/wallet_addEthereumChain
- sendTransaction(Transfer)
Please head over to https://docs.bitkeep.com/en/docs/guide/wallet/ethereum.html#eth-requestaccounts to check in detail about the method and it's usages.
Ethereum JSON-RPC Methods
For the Ethereum JSON-RPC API, please see the Ethereum wiki (opens new window). How to use reference to API Playground (opens new window).
- eth_accounts(opens new window)
- eth_call(opens new window)
- eth_getBalance(opens new window)
- eth_sendTransaction(opens new window)
- eth_sign
const Provider = getProvider();
await Provider.request({method:"eth_accounts", params:[]})
await Provider.request({method:"eth_getBalance", params:[]})
Event listeners
Notifies when address and network are changed . used eventemitter3
const Provider = getProvider();
// reomove all listeners
Provider.removeAllListeners();
function handleAccountsChainChanged() {
Provider.on('accountsChanged', ([address]) => {
// Handle the new accounts, or lack thereof.
// "accounts" will always be an array, but it can be empty.
alert('address changed');
});
Provider.on('chainChanged', async (chainId) => {
// Handle the new chain.
// Correctly handling chain changes can be complicated.
// We recommend reloading the page unless you have good reason not to.
alert('chainid changed');
});
}
Also, don't forget to remove listeners once you are done listening to them (for example on component unmount in React). Prevent multiple listening, and clear it before listening removeAllListeners
.
const Provider = getProvider();
function handleAccountsChanged(accounts) {
// ...
}
Provider.on('accountsChanged', handleAccountsChanged);
//remove
Provider.removeAllListeners(); //remove all
Provider.removeListener('accountsChanged', handleAccountsChanged); // only remove accountsChanged
accountsChanged
The Bitget provider emits this event whenever the return value of the eth_accounts RPC method changes. eth_accounts returns an array that is either empty or contains a single account address. The returned address, if any, is the address of the most recently used account that the caller is permitted to access. Callers are identified by their URL origin, which means that all sites with the same origin share the same permissions.
This means that accountsChanged will be emitted whenever the user's exposed account address changes.
const Provider = getProvider();
Provider.on('accountsChanged', handler: (accounts: Array<string>) => void);
chainChanged
The Bitget provider emits this event when the currently connected chain changes.
All RPC requests are submitted to the currently connected chain. Therefore, it's critical to keep track of the current chain ID by listening for this event.
We strongly recommend reloading the page on chain changes, unless you have good reason not to.
const Provider = getProvider();
Provider.on('accountsChanged', handler: (accounts: Array<string>) => void);
Signing Data
eth_sign
personal_sign
eth_signTypedData
eth_signTypedData_v3
eth_signTypedData_v4
You can refer to docs
Errors
All errors thrown or returned by the MetaMask provider follow this interface:
interface ProviderRpcError extends Error {
message: string;
code: number;
data?: unknown;
}
The ethereum.request(args) method throws errors eagerly. You can often use the error code property to determine why the request failed. Common codes and their meaning include:
4001
- The request was rejected by the user
-32603
- Internal error or The parameters were invalid
npm package using Onboard
onboard (opens new window) Onboard supports Bitget Wallet by default and can be used directly. This is a simple example.
Check the official demo(opens new window)
Install
Install npm package
yarn add @web3-onboard/core @web3-onboard/injected-wallets ethers
Then initialize the application
import Onboard from '@web3-onboard/core'
import injectedModule, { ProviderLabel } from '@web3-onboard/injected-wallets'
import { ethers } from 'ethers'
const MAINNET_RPC_URL = 'https://mainnet.infura.io/v3/<INFURA_KEY>'
const injected = injectedModule({
// do a manual sort of injected wallets so that BitKeep ordered first
sort: wallets => {
const bitKeep = wallets.find(
({ label }) => label === ProviderLabel.BitKeep
)
return (
[
bitKeep,
...wallets.filter(
({ label }) =>
label !== ProviderLabel.BitKeep
)
]
// remove undefined values
.filter(wallet => wallet)
)
},
})
const appMetadata = {
name: 'BitKeep',
icon: `<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 0C27.942 0 36 8.05967 36 18C36 27.942 27.942 36 18 36C8.05967 36 0 27.9413 0 18C0 8.05967 8.05967 0 18 0Z" fill="#7524F9"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M28 13.1817V14.2863C28.0002 14.3931 27.9714 14.4981 27.9165 14.5907C27.8616 14.6833 27.7826 14.7601 27.6875 14.8135L24.0242 16.8686L27.2969 18.6995C27.5108 18.8196 27.6884 18.9924 27.8118 19.2005C27.9353 19.4085 28.0002 19.6445 28 19.8847V22.8302C28.0003 23.0705 27.9355 23.3066 27.812 23.5148C27.6886 23.723 27.5109 23.8959 27.2969 24.0161L18.6898 28.8168C18.4761 28.9368 18.2336 29 17.9867 29C17.7399 29 17.4974 28.9368 17.2836 28.8168L14.4672 27.235C14.4196 27.2084 14.3802 27.17 14.3527 27.1238C14.3253 27.0776 14.3108 27.0252 14.3108 26.9718C14.3108 26.9184 14.3253 26.866 14.3527 26.8198C14.3802 26.7736 14.4196 26.7352 14.4672 26.7086L23.7641 21.5052C23.7877 21.4918 23.8074 21.4727 23.8211 21.4496C23.8347 21.4265 23.8419 21.4004 23.8419 21.3738C23.8419 21.3472 23.8347 21.321 23.8211 21.2979C23.8074 21.2749 23.7877 21.2557 23.7641 21.2423L20.3125 19.3035C20.2175 19.2502 20.1097 19.2221 20 19.2221C19.8903 19.2221 19.7825 19.2502 19.6875 19.3035L10.2445 24.5927C10.1733 24.6327 10.0924 24.6538 10.0102 24.6538C9.92788 24.6538 9.84704 24.6327 9.77578 24.5927L8.70625 23.9979C8.4913 23.8779 8.31277 23.7048 8.18875 23.4961C8.06472 23.2875 7.99961 23.0507 8 22.8096V21.6055C7.99995 21.5254 8.02158 21.4468 8.06273 21.3774C8.10387 21.3081 8.16307 21.2505 8.23438 21.2104L21.7734 13.6443C21.7971 13.631 21.8168 13.6118 21.8304 13.5887C21.8441 13.5657 21.8513 13.5395 21.8513 13.5129C21.8513 13.4863 21.8441 13.4601 21.8304 13.4371C21.8168 13.414 21.7971 13.3948 21.7734 13.3815L18.3164 11.4358C18.2214 11.3825 18.1136 11.3544 18.0039 11.3544C17.8942 11.3544 17.7864 11.3825 17.6914 11.4358L8.46875 16.5936C8.42127 16.6202 8.36741 16.6343 8.31258 16.6343C8.25775 16.6343 8.20389 16.6203 8.15639 16.5937C8.10889 16.567 8.06944 16.5287 8.04199 16.4826C8.01454 16.4364 8.00006 16.384 8 16.3307V13.1672C7.99971 12.9269 8.06454 12.6907 8.18798 12.4825C8.31142 12.2743 8.4891 12.1015 8.70313 11.9813L17.3086 7.18212C17.5219 7.0628 17.7637 7 18.0098 7C18.2558 7 18.4976 7.0628 18.7109 7.18212L27.2969 11.998C27.5106 12.118 27.688 12.2905 27.8114 12.4983C27.9349 12.706 27.9999 12.9417 28 13.1817Z" fill="white"/>
</svg>
`,
description: 'The multi-chain wallet chosen by 10 million users',
recommendedInjectedWallets: [
{ name: 'BitKeep', url: 'https://bitkeep.com/en/download?type=2' },
]
}
const onboard = Onboard({
wallets: [injected],
chains: [
{
id: '0x1',
token: 'ETH',
label: 'Ethereum Mainnet',
rpcUrl: MAINNET_RPC_URL
}
],
appMetadata
})
const wallets = await onboard.connectWallet()
console.log(wallets)
if (wallets[0]) {
// create an ethers provider with the last connected wallet provider
const ethersProvider = new ethers.providers.Web3Provider(wallets[0].provider, 'any')
// if using ethers v6 this is:
// ethersProvider = new ethers.BrowserProvider(wallet.provider, 'any')
const signer = ethersProvider.getSigner()
// send a transaction with the ethers provider
const txn = await signer.sendTransaction({
to: '0x',
value: 100000000000000
})
const receipt = await txn.wait()
console.log(receipt)
}
Solutions for possible errors:
https://docs.bitkeep.com/guide/wallet/faq.html#faqs-about-bitkeep-chrome-extension
Wrap
🛑 Have doubts and need support? Join our Discord Server and ping the Dev Rel team for support or interact with other blockchain developers and fellow builders!
💪🏼 Not tired and want to keep building? Head over to https://www.mantle.xyz/blog/developers and check out an amazing list of tutorials to keep building cool dApps on Mantle Network!
Ciao! 👋🏼