Skip to main content

Building a Wallet

The @thirdweb-dev/wallets package provides a set of pre-built components and functionality for creating and managing cryptocurrency wallets.

The following will guide you through how you can create your own wallet in a few simple steps:

  1. Implement your own Connector class
  2. Implement your own AbstractBrowserWallet class
  3. Expose your wallet to React and React Native wallet connect button

At the end of this guide you should have a fully functional wallet that can be used with the thirdweb TS, React and React Native SDKs.

1. Extending the Connector class

The Connector abstract class is the interface between your wallet core functionality and the actual wallet class you'll use in your application.

This is the biggest part of the wallet implementation and allows to bridge any wallet provider to a standardized interface.

Interface

export class MyConnector extends Connector {
connect(args?: ConnectParams<TConnectParams>): Promise<string>
disconnect(): Promise<void>
getAddress(): Promise<string>
getSigner(): Promise<Signer>
getProvider(): Promise<providers.Provider>
switchChain(chainId: number): Promise<void>
isConnected(): Promise<boolean>
setupListeners(): Promise<void>
updateChains(chains: Chain[]): void
}

You can choose to implement all or part of the connector functionality.

Required methods

connect

This method should trigger the connection flow of your wallet with the user's app.

Configuration

args

The arguments needed to connect your wallet. This is specific to your wallet implementation which is why we leave it open for you to add custom arguments here.

Returns a string containing the wallet address, or undefined if the connection failed.

abstract connect(args?: ConnectParams<TConnectParams>): Promise<string>;

ConnectParams<TOpts extends Record<string, any> = {}> = {
chainId?: number;
} & TOpts;
getSigner

Returns a Promise<Signer> with the ethers signer associated with your wallet.

getProvider

Returns a Promise<providers.Provider> with the ethers provider associated with your wallet.

disconnect

Disconnect the currently connected wallet from your app.

isConnected

Returns a Promise<boolean> indicating whether the wallet is connected or not.

getAddress

Returns a Promise<string> with the currently connected wallet address.

Optional methods

You can throw an exception or leave the implementation empty if you don't want to implement these methods.

switchChain

Switch the chain the wallet is connected to.

setupListeners

This method should set all listeners needed for the wallet to work. It will be used by the AbstractClientWallet class to setup the listeners when the wallet is connected.

updateChains

Update the chains the wallet can connect to.

Configuration

chains

The chains that are supported by the wallet. Defaults to our default chains.

Must be an array of Chain objects.

type Chain = {
chainId: number;
chainName: string;
nativeCurrency: {
name: string;
symbol: string;
decimals: number;
};
rpcUrls: string[];
blockExplorerUrls: string[];
};

2. Extending the AbstractClientWallet class

Now that the hard part is done, the rest is easy, we just need to wrap our connector in a AbstractClientWallet class.

The AbstractClientWallet class is the base class that provides an interface for interacting with your connector on one side and with applications on the other.

The main method that needs to be overridden is the getConnector method. This method should return a Promise that resolves to a the Connector class that you implemented.

export class MyWallet extends AbstractClientWallet {
async getConnector(): Promise<Connector> {
return new MyConnector();
}
}

You can add expose any custom logic here as the public API for your wallet.

Required Methods

getConnector

Returns a Promise<Connector> with the connector class that you implemented.

Using your new wallet

At this point you should be able to instantiate your new wallet and calling connect on it.

const wallet = new MyWallet();
wallet.connect();

3. Exposing your wallet to React and React Native

The last step is to expose your wallet to React and React Native. This is done by exposing a function for the SDK to access your wallet lazily. You can also let users pass custom params for your wallet as arguments to this function.

const myWallet = (myParams?: MyParams): ConfiguredWallet => {
return {
id: MetaMaskWallet.id,
meta: {
name: "MyWallet",
iconURL: "{{link_to_my_wallet_icon}}",
},
create: (options: WalletOptions) => {
return new MyWallet({ ...options, ...myParams });
},
};
};

You can now use your wallet in the Connect Wallet button! Simply add it to the supportedWallets property of the ThirdwebProvider.

<ThirdwebProvider supportedWallets={[myWallet()]}>
<App />
</ThirdwebProvider>

Contributing to the Wallets package

If you think your wallet implementation would be useful to others, please consider sharing it by opening a PR to the @thirdweb-dev/wallets package.