Skip to content

Commit

Permalink
feat: add Brave Wallet (#448)
Browse files Browse the repository at this point in the history
  • Loading branch information
markdalgleish committed May 31, 2022
1 parent 1b08172 commit 4be196e
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 9 deletions.
7 changes: 7 additions & 0 deletions .changeset/honest-numbers-push.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@rainbow-me/rainbowkit': patch
---

Ensure Brave Wallet and Tokenary aren’t detected as MetaMask

Both Brave Wallet and Tokenary set `window.ethereum.isMetaMask` to `true` which causes issues with the logic for providing the fallback "Injected Wallet" option. Similar to wagmi, we now detect when MetaMask is being impersonated by these wallets.
9 changes: 9 additions & 0 deletions .changeset/shiny-squids-sniff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@rainbow-me/rainbowkit': patch
---

Add Brave Wallet support

Brave Wallet is now included as part of the default set of wallets returned from `getDefaultWallets`, but note that is only visible within the Brave browser to avoid prompting users to download an entirely different web browser.

Brave Wallet is also included as part of the `wallet` object to support its usage in [custom wallet lists,](https://www.rainbowkit.com/docs/custom-wallet-list) e.g. `wallet.brave({ chains, shimDisconnect: true })`.
16 changes: 8 additions & 8 deletions packages/rainbowkit/src/wallets/getDefaultWallets.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Chain } from '../components/RainbowKitProvider/RainbowKitChainContext';
import { WalletList } from './Wallet';
import { connectorsForWallets } from './connectorsForWallets';
import { brave } from './walletConnectors/brave/brave';
import { coinbase } from './walletConnectors/coinbase/coinbase';
import { injected } from './walletConnectors/injected/injected';
import { metaMask } from './walletConnectors/metaMask/metaMask';
import { isMetaMask, metaMask } from './walletConnectors/metaMask/metaMask';
import { rainbow } from './walletConnectors/rainbow/rainbow';
import { walletConnect } from './walletConnectors/walletConnect/walletConnect';

Expand All @@ -20,23 +21,22 @@ export const getDefaultWallets = ({
const needsInjectedWalletFallback =
typeof window !== 'undefined' &&
window.ethereum &&
!window.ethereum.isMetaMask &&
!window.ethereum.isCoinbaseWallet;
!isMetaMask(window.ethereum) &&
!window.ethereum.isCoinbaseWallet &&
!window.ethereum.isBraveWallet;

const wallets: WalletList = [
{
groupName: 'Popular',
wallets: [
rainbow({ chains }),
coinbase({ appName, chains }),
metaMask({
chains,
shimDisconnect: true,
}),
metaMask({ chains, shimDisconnect: true }),
walletConnect({ chains }),
brave({ chains, shimDisconnect: true }),
...(needsInjectedWalletFallback
? [injected({ chains, shimDisconnect: true })]
: []),
walletConnect({ chains }),
],
},
];
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions packages/rainbowkit/src/wallets/walletConnectors/brave/brave.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* eslint-disable sort-keys-fix/sort-keys-fix */
import { InjectedConnector } from 'wagmi/connectors/injected';
import { Chain } from '../../../components/RainbowKitProvider/RainbowKitChainContext';
import { Wallet } from '../../Wallet';

export interface BraveOptions {
chains: Chain[];
shimDisconnect?: boolean;
}

export const brave = ({ chains, shimDisconnect }: BraveOptions): Wallet => ({
id: 'brave',
name: 'Brave Wallet',
iconUrl: async () => (await import('./brave.svg')).default,
iconBackground: '#fff',
installed:
typeof window !== 'undefined' && window.ethereum?.isBraveWallet === true,
downloadUrls: {
// We're opting not to provide a download prompt if Brave isn't the current
// browser since it's unlikely to be a desired behavior for users. It's
// more of a convenience for users who are already using Brave rather than
// an explicit wallet choice for users coming from other browsers.
},
createConnector: () => ({
connector: new InjectedConnector({
chains,
options: { shimDisconnect },
}),
}),
});
2 changes: 2 additions & 0 deletions packages/rainbowkit/src/wallets/walletConnectors/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { argent } from './argent/argent';
import { brave } from './brave/brave';
import { coinbase } from './coinbase/coinbase';
import { imToken } from './imToken/imToken';
import { injected } from './injected/injected';
Expand All @@ -11,6 +12,7 @@ import { walletConnect } from './walletConnect/walletConnect';

export const wallet = {
argent,
brave,
coinbase,
imToken,
injected,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,36 @@ export interface MetaMaskOptions {
shimDisconnect?: boolean;
}

export function isMetaMask(ethereum: NonNullable<typeof window['ethereum']>) {
// Logic borrowed from wagmi's MetaMaskConnector
// https://github.com/tmm/wagmi/blob/main/packages/core/src/connectors/metaMask.ts
const isMetaMask = Boolean(ethereum.isMetaMask);

if (!isMetaMask) {
return false;
}

// Brave tries to make itself look like MetaMask
// Could also try RPC `web3_clientVersion` if following is unreliable
if (ethereum.isBraveWallet && !ethereum._events && !ethereum._state) {
return false;
}

if (ethereum.isTokenary) {
return false;
}

return true;
}

export const metaMask = ({
chains,
shimDisconnect,
}: MetaMaskOptions): Wallet => {
const isMetaMaskInjected =
typeof window !== 'undefined' && window.ethereum?.isMetaMask;
typeof window !== 'undefined' &&
typeof window.ethereum !== 'undefined' &&
isMetaMask(window.ethereum);

const shouldUseWalletConnect = isMobile() && !isMetaMaskInjected;

Expand Down
11 changes: 11 additions & 0 deletions site/data/docs/custom-wallet-list.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ wallet.argent(options: {
});
```

#### Brave Wallet

```tsx
import { wallet } from '@rainbow-me/rainbowkit';

wallet.brave(options: {
chains: Chain[];
shimDisconnect?: boolean;
});
```

#### Coinbase Wallet

```tsx
Expand Down

2 comments on commit 4be196e

@vercel
Copy link

@vercel vercel bot commented on 4be196e May 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 4be196e May 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.