Bitget Wallet Support for dApps on Mantle Network

09/25/237 min read

Mantleby Mantle

Developers

Web3

Bitget Wallet Support for dApps on Mantle Network

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:

  1. Detect the Ethereum provider (window?.bitkeep?.ethereum)
  2. Detect which Ethereum network the user is connected to
  3. 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

  1. eth_requestAccounts
  2. wallet_watchAsset
  3. wallet_switchEthereumChain/wallet_addEthereumChain
  4. 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).

 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! 👋🏼


加入社区