Wallet Client Setup

Quickly setup a few thing to get you up and running in 15 minutes

Elements requires a few wallet methods to work. We have created an interface so that you can bring your own wallet (BYOW) and elements will always work!

For this purpose, elements needs you to pass in a wallet client.

WalletClient

This is an object that has the following methods that the elements components use:

  • enable: function that enables chain(s) on the wallet.

  • getAccount: function that returns the account for a given chain id

  • getSigner: function that returns a signer for a given chain id

  • network: network settings for the SDK (this is optional and by default set to mainnet)

    • We export a NETWORK enum from elements which you can use to set this property

Here's the interface:

enum NETWORK {
  MAINNET = 'mainnet`
  TESTNET = 'testnet`
}

interface WalletClient {
  enable: (chainIds: string | string[]) => Promise<void>
  getAccount: (chainId: string) => Promise<Account>
  getSigner: (chainId: string) => Promise<Signer>
  network?: NETWORK
}

Setup

You can do a custom implementation of wallet client. We have created examples of wallet clients with the most common wallet adapters in cosmos.

Cosmos Kit

// use-elements-wallet-client.ts
import { type WalletClient, NETWORK } from '@leapwallet/elements'
import { useWalletClient } from '@cosmos-kit/react'

const useElementsWalletClient = (): WalletClient => {
    const { client } = useWalletClient()

    const walletClient: WalletClient = useMemo(() => {
      return {
        enable: (chainIds: string | string[]) => {
          return client!.enable!(chainIds)
        },
        getAccount: async (chainId: string) => {
          await client!.enable!(chainId)
          const result = await client!.getAccount!(chainId)
          return {
            bech32Address: result.address,
            pubKey: result.pubkey,
            isNanoLedger: !!result.isNanoLedger
          }
        },
        getSigner: async (chainId: string) => {
          const signer = client!.getOfflineSignerDirect!(chainId)
          const aminoSigner = client!.getOfflineSignerAmino!(chainId)
          
          return {
            signDirect: async (address, signDoc) => {
              const result = await signer.signDirect(address, signDoc)
              return {
                signature: new Uint8Array(Buffer.from(result.signature.signature, 'base64')),
                signed: result.signed
              }
            },
            signAmino: async (address, signDoc) => {
              const result = await aminoSigner.signAmino(address, signDoc)
              return {
                signature: new Uint8Array(Buffer.from(res.signature.signature, 'base64')),
                signed: res.signed
              }
            },
            network: NETWORK.TESTNET // to enable testnet in Elements
          }
        },
      }
    }, [client])

    return walletClient;
}

WalletConfig

This is an object that has methods and properties that the Elements components use:

  1. userAddress string | undefined

    Description - user's address for the primary connected chain. If undefined is passed, it is inferred as the wallet no connected state.

  2. walletClient WalletClient

    Description - wallet client described above to sign transactions

  3. connectWallet (chainId?: string) => Promise<void>

    Description - let's Elements trigger your dApps' wallet connection flow, accepts an optional chain ID parameter to specify which chain to connect with.

CosmosKit Setup Contd.

// use-elements-wallet-config.ts

import { useMemo } from 'react'
import { WalletClientContext } from '@leapwallet/elements'
import { useChain, useManager, useWallet } from '@cosmos-kit/react'
import { chains } from 'chain-registry'

import { useElementsWalletClient } from './use-elements-wallet-client'

export const useElementsWalletConfig = (
  defaultChain = 'osmosis-1'
): WalletClientContext => {
  const walletClient = useElementsWalletClient()
  const { address } = useChain(
    chains.find((c) => c.chain_id === defaultChain)?.chain_name ?? 'osmosis'
  )
  const { getWalletRepo } = useManager()
  const { mainWallet } = useWallet()

  const walletStatus = mainWallet?.walletStatus

  const walletConfig = useMemo(() => {
    return {
      userAddress: walletStatus === 'Connected' ? address : undefined,
      walletClient,
      connectWallet: (chainId: unknown) => {
        let _chainId = chainId
        if (typeof chainId !== 'string') {
          // default to osmosis chain - you can set it to any chain of choice
          _chainId = 'osmosis-1'
        }
        const chain = chains.find((c) => c.chain_id === _chainId)
        if (!chain) {
          throw new Error(`Chain ${chainId} not supported`)
        }
        return getWalletRepo(chain.chain_name).connect()
      }
    } as const
  }, [address, getWalletRepo, walletStatus, walletClient])
  
  return walletConfig
}

Last updated