RainbowKit Integration

Use this guide if your app uses RainbowKit + Wagmi.

Until CipherTrade is merged upstream, you can add it manually as a custom wallet.


Expected behavior

Your integration should:

This matters because CipherTrade is not only a WalletConnect destination. It may also be available as an injected EIP-1193 provider.


Step 1 — add the custom wallet file

Create cipherTradeWallet.ts and use the implementation below.

import type {
  RainbowKitWalletConnectParameters,
  Wallet,
  WalletDetailsParams,
} from '@rainbow-me/rainbowkit'
import { getWalletConnectConnector } from '@rainbow-me/rainbowkit'
import type { EIP1193Provider } from 'viem'
import { createConnector } from 'wagmi'
import { injected } from 'wagmi/connectors'

export type CipherTradeWalletOptions = {
  projectId: string
  walletConnectParameters?: RainbowKitWalletConnectParameters
}

type FlaggedEthereum = {
  providers?: FlaggedEthereum[]
  isCipherTrade?: boolean
}

function getExplicitInjectedProvider(
  flag: 'isCipherTrade',
): FlaggedEthereum | undefined {
  if (typeof window === 'undefined') return
  const eth = window.ethereum as FlaggedEthereum | undefined
  if (typeof eth === 'undefined') return
  const providers = eth.providers
  if (providers) return providers.find((p: FlaggedEthereum) => p[flag])
  return eth[flag] ? eth : undefined
}

function hasInjectedCipherTrade(): boolean {
  return typeof getExplicitInjectedProvider('isCipherTrade') !== 'undefined'
}

function getInjectedCipherTradeConnector() {
  return (walletDetails: WalletDetailsParams) =>
    createConnector((config) => ({
      ...injected({
        target: () => {
          const provider = getExplicitInjectedProvider('isCipherTrade')
          if (!provider) {
            throw new Error('CipherTrade injected provider not found')
          }
          return {
            id: walletDetails.rkDetails.id,
            name: walletDetails.rkDetails.name,
            provider: provider as EIP1193Provider,
          }
        },
      })(config),
      ...walletDetails,
    }))
}

export function cipherTradeWallet({
  projectId,
  walletConnectParameters,
}: CipherTradeWalletOptions): Wallet {
  const isCipherTradeInjected = hasInjectedCipherTrade()
  const shouldUseWalletConnect = !isCipherTradeInjected

  const getUriMobile = (uri: string) =>
    `ciphertrade://wc?uri=${encodeURIComponent(uri)}`

  return {
    id: 'ciphertrade',
    name: 'CipherTrade',
    rdns: 'org.ciphertrade.app',
    iconUrl: async () => '<https://ciphertrade.org/wc-app-icon.png>',
    iconBackground: '#131C2B',
    installed: isCipherTradeInjected || undefined,
    downloadUrls: {
      android:
        '<https://play.google.com/store/apps/details?id=org.ciphertrade.app>',
      qrCode: '<https://ciphertrade.org>',
    },
    mobile: {
      getUri: shouldUseWalletConnect ? getUriMobile : undefined,
    },
    qrCode: shouldUseWalletConnect
      ? {
          getUri: (uri: string) => uri,
          instructions: {
            learnMoreUrl: '<https://ciphertrade.org>',
            steps: [
              {
                description: 'Scan this QR code with the CipherTrade app.',
                step: 'scan',
                title: 'Scan with CipherTrade',
              },
            ],
          },
        }
      : undefined,
    createConnector: shouldUseWalletConnect
      ? getWalletConnectConnector({ projectId, walletConnectParameters })
      : getInjectedCipherTradeConnector(),
  }
}

Step 2 — add CipherTrade to your wallet list

import { connectorsForWallets } from '@rainbow-me/rainbowkit'
import { cipherTradeWallet } from './cipherTradeWallet'

const connectors = connectorsForWallets(
  [
    {
      groupName: 'Recommended',
      wallets: [
        cipherTradeWallet({
          projectId: 'YOUR_PROJECT_ID',
        }),
      ],
    },
  ],
)

Step 3 — what this implementation does