Skip to content

Commit

Permalink
Add rainbow wallet (#1884)
Browse files Browse the repository at this point in the history
Co-authored-by: Trung-Tin Pham <[email protected]>
  • Loading branch information
vutuanlinh2k2 and AtelyPham authored Dec 11, 2023
1 parent efb4f5e commit 21aa4bf
Show file tree
Hide file tree
Showing 16 changed files with 427 additions and 70 deletions.
6 changes: 3 additions & 3 deletions apps/bridge-dapp/src/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ const AppRoutes = () => {
index={true}
element={
<CSuspense>
<RequireNoteAccountRoute redirect={BRIDGE_PATH}>
<RequireNoteAccountRoute redirect={`/${BRIDGE_PATH}`}>
<Account />
</RequireNoteAccountRoute>
</CSuspense>
Expand All @@ -211,7 +211,7 @@ const AppRoutes = () => {
path={ACCOUNT_TRANSACTIONS_PATH}
element={
<CSuspense>
<RequireNoteAccountRoute redirect={BRIDGE_PATH}>
<RequireNoteAccountRoute redirect={`/${BRIDGE_PATH}`}>
<AccountTransactions />
</RequireNoteAccountRoute>
</CSuspense>
Expand All @@ -221,7 +221,7 @@ const AppRoutes = () => {
path=":txHash"
element={
<CSuspense>
<RequireNoteAccountRoute redirect={BRIDGE_PATH}>
<RequireNoteAccountRoute redirect={`/${BRIDGE_PATH}`}>
<AccountTransactionDetail />
</RequireNoteAccountRoute>
</CSuspense>
Expand Down
2 changes: 2 additions & 0 deletions libs/api-provider-environment/src/WebbProvider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ const WebbProviderInner: FC<WebbProviderProps> = ({ children, appEvent }) => {
case WebbErrorCodes.UnselectedChain:
break;
case WebbErrorCodes.MetaMaskExtensionNotInstalled:
case WebbErrorCodes.RainbowExtensionNotInstalled:
case WebbErrorCodes.PolkaDotExtensionNotInstalled:
case WebbErrorCodes.TalismanExtensionNotInstalled:
case WebbErrorCodes.SubWalletExtensionNotInstalled:
Expand Down Expand Up @@ -394,6 +395,7 @@ const WebbProviderInner: FC<WebbProviderProps> = ({ children, appEvent }) => {

case WalletId.MetaMask:
case WalletId.WalletConnectV2:
case WalletId.Rainbow:
{
const connector = walletsConfig[wallet.id].connector;
if (!connector) {
Expand Down
2 changes: 2 additions & 0 deletions libs/dapp-config/src/wallets/injected/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as MetaMaskConnector } from './metamask';
export { default as RainbowConnector } from './rainbow';
41 changes: 41 additions & 0 deletions libs/dapp-config/src/wallets/injected/metamask.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { InjectedConnectorOptions, WindowProvider } from '@wagmi/core';
import { InjectedConnector } from 'wagmi/connectors/injected';
import { Chain } from 'wagmi';
import { getExplicitInjectedProvider } from './utils';

// handle multi injected connectors problem with providers
// Related: https://github.com/wevm/wagmi/discussions/742
export default class MetaMaskConnector extends InjectedConnector {
readonly id = 'metamask';
readonly name = 'Metamask';
readonly ready =
typeof window != 'undefined' && !!this.#findProvider(window.ethereum);

#provider?: Window['ethereum'];

constructor({
chains,
options,
}: { chains?: Chain[]; options?: InjectedConnectorOptions } = {}) {
super({ chains, options: { name: 'MetaMask Wallet', ...options } });
}

async getProvider() {
if (typeof window !== 'undefined') {
this.#provider = this.#findProvider(window.ethereum);
// this.#provider = getExplicitInjectedProvider('isMetaMask');
}
return this.#provider;
}

#getReady(provider?: WindowProvider) {
if (!provider?.isMetaMask) return;
return provider;
}

#findProvider(provider?: WindowProvider) {
if (provider?.providers)
return getExplicitInjectedProvider(provider.providers, 'isMetaMask');
return this.#getReady(provider);
}
}
40 changes: 40 additions & 0 deletions libs/dapp-config/src/wallets/injected/rainbow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { InjectedConnectorOptions, WindowProvider } from '@wagmi/core';
import { InjectedConnector } from 'wagmi/connectors/injected';
import { Chain } from 'wagmi';
import { getExplicitInjectedProvider } from './utils';

// handle multi injected connectors problem with providers
// Related: https://github.com/wevm/wagmi/discussions/742
export default class RainbowConnector extends InjectedConnector {
readonly id = 'rainbow';
readonly name = 'rainbow';
readonly ready =
typeof window != 'undefined' && !!this.#findProvider(window.ethereum);

#provider?: Window['ethereum'];

constructor({
chains,
options,
}: { chains?: Chain[]; options?: InjectedConnectorOptions } = {}) {
super({ chains, options: { name: 'Rainbow Wallet', ...options } });
}

async getProvider() {
if (typeof window !== 'undefined') {
this.#provider = this.#findProvider(window.ethereum);
}
return this.#provider;
}

#getReady(provider?: WindowProvider) {
if (!provider?.isRainbow) return;
return provider;
}

#findProvider(provider?: WindowProvider) {
if (provider?.providers)
return getExplicitInjectedProvider(provider.providers, 'isRainbow');
return this.#getReady(provider);
}
}
24 changes: 24 additions & 0 deletions libs/dapp-config/src/wallets/injected/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { InjectedProviderFlags, WindowProvider } from 'wagmi/window';

/*
* Returns the explicit window provider that matches the flag and the flag is true
*/
export function getExplicitInjectedProvider(
providers: WindowProvider[] | undefined,
flag: keyof InjectedProviderFlags
): WindowProvider | undefined {
if (typeof window === 'undefined' || typeof window.ethereum === 'undefined')
return;
return providers
? providers
.filter((provider) => provider[flag])
// if not targeting rainbow wallet, prevent rainbow wallet from being used
.find(
(provider: any) =>
provider?.['rainbowIsDefaultProvider'] ===
(flag === 'isRainbow' ? true : undefined)
)
: window.ethereum[flag]
? window.ethereum
: undefined;
}
7 changes: 5 additions & 2 deletions libs/dapp-config/src/wallets/wallet-config.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@

import type { InjectedExtension } from '@polkadot/extension-inject/types';
import type { SupportedBrowsers } from '@webb-tools/browser-utils/platform';
import type { MetaMaskConnector } from 'wagmi/connectors/metaMask';
import type { WalletConnectConnector } from 'wagmi/connectors/walletConnect';
import { MetaMaskConnector, RainbowConnector } from './injected';

export type SupportedConnector = MetaMaskConnector | WalletConnectConnector;
export type SupportedConnector =
| MetaMaskConnector
| WalletConnectConnector
| RainbowConnector;

export interface WalletConfig {
id: number;
Expand Down
38 changes: 34 additions & 4 deletions libs/dapp-config/src/wallets/wallets-config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import { WalletId } from '@webb-tools/dapp-types/WalletId';
import {
MetaMaskIcon,
PolkadotJsIcon,
RainbowIcon,
SubWalletIcon,
TalismanIcon,
WalletConnectIcon,
} from '@webb-tools/icons';
import { MetaMaskConnector } from 'wagmi/connectors/metaMask';
import { WalletConnectConnector } from 'wagmi/connectors/walletConnect';
import { MetaMaskConnector, RainbowConnector } from './injected';
import { chainsConfig as evmChainsConfig } from '../chains/evm';
import { HUBBLE_BRIDGE_DAPP_NAME } from '../constants';
import getPolkadotBasedWallet from '../utils/getPolkadotBasedWallet';
import { WalletConfig } from './wallet-config.interface';
import type { WalletConfig } from './wallet-config.interface';

const ANY_EVM = [
PresetTypedChainId.EthereumMainNet,
Expand Down Expand Up @@ -60,6 +61,9 @@ export const connectors = {
projectId: process.env['BRIDGE_DAPP_WALLET_CONNECT_PROJECT_ID'] ?? '',
},
}),
[WalletId.Rainbow]: new RainbowConnector({
chains: Object.values(evmChainsConfig),
}),
};

export const walletsConfig: Record<number, WalletConfig> = {
Expand Down Expand Up @@ -93,8 +97,8 @@ export const walletsConfig: Record<number, WalletConfig> = {
enabled: true,
async detect() {
const metaMaskConnector = connectors[WalletId.MetaMask];
const provier = await metaMaskConnector.getProvider();
if (!provier) {
const provider = await metaMaskConnector.getProvider();
if (!provider) {
return;
}

Expand Down Expand Up @@ -124,6 +128,32 @@ export const walletsConfig: Record<number, WalletConfig> = {
homeLink: 'https://walletconnect.com/',
connector: connectors[WalletId.WalletConnectV2],
},
[WalletId.Rainbow]: {
id: WalletId.Rainbow,
Logo: <RainbowIcon />,
name: 'rainbow',
title: 'Rainbow',
platform: 'EVM',
enabled: true,
async detect() {
const conn = connectors[WalletId.Rainbow];
const provider = await conn.getProvider();
if (!provider) {
return;
}

return conn;
},
supportedChainIds: [...ANY_EVM],
homeLink: 'https://rainbow.me/',
connector: connectors[WalletId.Rainbow],
installLinks: {
[SupportedBrowsers.FireFox]:
'https://addons.mozilla.org/en-US/firefox/addon/rainbow-extension/',
[SupportedBrowsers.Chrome]:
'https://chrome.google.com/webstore/detail/rainbow/opfgelmcmbiajamepnmloijbpoleiama',
},
},
[WalletId.Talisman]: {
id: WalletId.Talisman,
Logo: <TalismanIcon />,
Expand Down
1 change: 1 addition & 0 deletions libs/dapp-types/src/WalletId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export enum WalletId {
Polkadot = 1,
MetaMask,
WalletConnectV2,
Rainbow,
OneWallet,
Talisman,
SubWallet,
Expand Down
8 changes: 8 additions & 0 deletions libs/dapp-types/src/WebbError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export enum WebbErrorCodes {
SubWalletExtensionNotInstalled,
/* MetaMasK extension not installed */
MetaMaskExtensionNotInstalled,
/* Rainbow extension not installed */
RainbowExtensionNotInstalled,
/* Unknown wallet */
UnknownWallet,
/* Runtime Error on the provider */
Expand Down Expand Up @@ -203,6 +205,12 @@ export class WebbError extends Error {
message: 'MetaMask extension no installed',
};

case WebbErrorCodes.RainbowExtensionNotInstalled:
return {
code,
message: 'Rainbow extension no installed',
};

case WebbErrorCodes.UnknownWallet:
return {
code: WebbErrorCodes.UnknownWallet,
Expand Down
3 changes: 3 additions & 0 deletions libs/dapp-types/src/errors/WalletNotInstalledError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ class WalletNotInstalledError extends WebbError {
case WalletId.MetaMask:
super(WebbErrorCodes.MetaMaskExtensionNotInstalled);
break;
case WalletId.Rainbow:
super(WebbErrorCodes.RainbowExtensionNotInstalled);
break;
case WalletId.Polkadot:
super(WebbErrorCodes.PolkaDotExtensionNotInstalled);
break;
Expand Down
Loading

0 comments on commit 21aa4bf

Please sign in to comment.