Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Metamask SDK integration with the metamask wallet connector #2077

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/rotten-lies-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@rainbow-me/rainbowkit": minor
"example": patch
---

Metamask SDK integration with the metamask wallet connector
2 changes: 1 addition & 1 deletion examples/with-create-react-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"typescript": "5.4.2",
"util": "0.12.5",
"viem": "2.9.31",
"wagmi": "^2.9.2",
"wagmi": "^2.10.7",
"@tanstack/react-query": "^5.28.4"
},
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion examples/with-next-app-i18n/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"react": "^18.3.0",
"react-dom": "^18.3.0",
"viem": "2.9.31",
"wagmi": "^2.9.2",
"wagmi": "^2.10.7",
"@tanstack/react-query": "^5.28.4"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/with-next-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"react": "^18.3.0",
"react-dom": "^18.3.0",
"viem": "2.9.31",
"wagmi": "^2.9.2",
"wagmi": "^2.10.7",
"@tanstack/react-query": "^5.28.4"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/with-next-custom-button/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"react": "^18.3.0",
"react-dom": "^18.3.0",
"viem": "2.9.31",
"wagmi": "^2.9.2",
"wagmi": "^2.10.7",
"@tanstack/react-query": "^5.28.4"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/with-next-mint-nft/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"react": "^18.3.0",
"react-dom": "^18.3.0",
"viem": "2.9.31",
"wagmi": "^2.9.2",
"wagmi": "^2.10.7",
"@tanstack/react-query": "^5.28.4"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/with-next-rainbow-button/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"react": "^18.3.0",
"react-dom": "^18.3.0",
"viem": "2.9.31",
"wagmi": "^2.9.2",
"wagmi": "^2.10.7",
"@tanstack/react-query": "^5.28.4"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/with-next-siwe-iron-session/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"react-dom": "^18.3.0",
"siwe": "^2.1.4",
"viem": "2.9.31",
"wagmi": "^2.9.2",
"wagmi": "^2.10.7",
"@tanstack/react-query": "^5.28.4"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/with-next-siwe-next-auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"react-dom": "^18.3.0",
"siwe": "^2.1.4",
"viem": "2.9.31",
"wagmi": "^2.9.2",
"wagmi": "^2.10.7",
"@tanstack/react-query": "^5.28.4"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/with-next-wallet-button/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"react": "^18.3.0",
"react-dom": "^18.3.0",
"viem": "2.9.31",
"wagmi": "^2.9.2",
"wagmi": "^2.10.7",
"@tanstack/react-query": "^5.28.4"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/with-next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"react": "^18.3.0",
"react-dom": "^18.3.0",
"viem": "2.9.31",
"wagmi": "^2.9.2",
"wagmi": "^2.10.7",
"@tanstack/react-query": "^5.28.4"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/with-remix/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"react": "^18.3.0",
"react-dom": "^18.3.0",
"viem": "2.9.31",
"wagmi": "^2.9.2",
"wagmi": "^2.10.7",
"@tanstack/react-query": "^5.28.4"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/with-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"react": "^18.3.0",
"react-dom": "^18.3.0",
"viem": "2.9.31",
"wagmi": "^2.9.2",
"wagmi": "^2.10.7",
"@tanstack/react-query": "^5.28.4"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"typescript": "5.4.2",
"viem": "2.9.31",
"vitest": "^0.33.0",
"wagmi": "^2.9.2",
"wagmi": "^2.10.7",
"dotenv": "^16.4.5"
},
"packageManager": "pnpm@9.1.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"react": "^18.3.0",
"react-dom": "^18.3.0",
"viem": "2.9.31",
"wagmi": "^2.9.2"
"wagmi": "^2.10.7"
},
"devDependencies": {
"@types/node": "^18.19.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"react": "^18.3.0",
"react-dom": "^18.3.0",
"viem": "2.9.31",
"wagmi": "^2.9.2"
"wagmi": "^2.10.7"
},
"devDependencies": {
"@types/node": "^18.19.3",
Expand Down
2 changes: 1 addition & 1 deletion packages/example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"react-dom": "^18.3.0",
"siwe": "^2.1.4",
"viem": "2.9.31",
"wagmi": "^2.9.2"
"wagmi": "^2.10.7"
},
"scripts": {
"dev": "next dev",
Expand Down
4 changes: 4 additions & 0 deletions packages/example/src/wagmi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ const sei = {
// Testing `preference` type
coinbaseWallet.preference = 'all';

metaMaskWallet.parameters = {
// infuraAPIKey: '01234',
};

export const config = getDefaultConfig({
appName: 'RainbowKit Demo',
projectId,
Expand Down
2 changes: 1 addition & 1 deletion packages/rainbow-button/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"react": ">=18",
"react-dom": ">=18",
"viem": "2.x",
"wagmi": "^2.9.0"
"wagmi": "^2.10.7"
},
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion packages/rainbowkit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"react": ">=18",
"react-dom": ">=18",
"viem": "2.x",
"wagmi": "^2.9.0"
"wagmi": "^2.10.7"
},
"devDependencies": {
"@testing-library/jest-dom": "^6.2.0",
Expand Down
8 changes: 8 additions & 0 deletions packages/rainbowkit/src/wallets/useWalletConnectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import {
rainbowKitConnectorWithWalletConnect,
} from './groupedWallets';
import { addRecentWalletId, getRecentWalletIds } from './recentWalletIds';
import {
METAMASK_WALLET_ID,
MetaMaskConnector,
} from './walletConnectors/metaMaskWallet/metaMaskWallet';

export interface WalletConnector extends WalletInstance {
ready?: boolean;
Expand Down Expand Up @@ -107,6 +111,10 @@ export function useWalletConnectors(
return provider.qrUrl;
}

if (connector.id === METAMASK_WALLET_ID) {
return (connector as unknown as MetaMaskConnector).getDisplayUri();
}

return new Promise<string>((resolve) =>
// Wagmi v2 doesn't have a return type for provider yet
// @ts-expect-error
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Implementation of MetaMask Wallet Connector

Rainbow kit relies on the [Wagmi library](https://github.com/wevm/wagmi/tree/main) and its connectors, but it wraps the connector in a custom “wallet” to add more functionality. The Wagmi [metamask connector](https://github.com/wevm/wagmi/blob/main/packages/connectors/src/metaMask.ts) use the [metamask sdk](https://github.com/MetaMask/metamask-sdk/tree/main).

Due to specific usage of Wagmi by RainbowKit, we had to fix some issues.

## Fix the `getChainId` function
RainbowKit requests the chainId from the connector before connecting to it.
In our case, we need to start the MetaMask connector even if the browser extension is not installed, to allow connection through the QR code.
However, the current implementation of the `getChainId` function in the MetaMask connector throws an error if the browser extension is not installed.

See the folowing call stack:
- [rainbowkit/packages/rainbowkit/src/components/ConnectOptions/DesktopOptions.tsx#selectWallet](https://github.com/EdouardBougon/rainbowkit/blob/497614b30db7e636b4e560f1b81f6a1315e13429/packages/rainbowkit/src/components/ConnectOptions/DesktopOptions.tsx#L149)
- [rainbowkit/packages/rainbowkit/src/components/ConnectOptions/DesktopOptions.tsx#connectToWallet](https://github.com/EdouardBougon/rainbowkit/blob/497614b30db7e636b4e560f1b81f6a1315e13429/packages/rainbowkit/src/components/ConnectOptions/DesktopOptions.tsx#L161)
- [wagmi/packages/connectors/src/metaMask.ts#connect](https://github.com/wevm/wagmi/blob/4e9493aa0fb2d7801040a4000e8c634eb0aba608/packages/connectors/src/metaMask.ts#L61)
- [metamask-sdk/packages/sdk/src/sdk.ts#connect](https://github.com/MetaMask/metamask-sdk/blob/23127c42357e93fa23968e769051ded8bcb9f718/packages/sdk/src/sdk.ts#L274)
- [metamask-sdk/packages/sdk/src/services/MetaMaskSDK/ConnectionManager/connect.ts#connect](https://github.com/MetaMask/metamask-sdk/blob/23127c42357e93fa23968e769051ded8bcb9f718/packages/sdk/src/services/MetaMaskSDK/ConnectionManager/connect.ts#L16)
- [metamask-sdk/packages/sdk/src/provider/initializeMobileProvider.ts#sendRequest](https://github.com/MetaMask/metamask-sdk/blob/90f2b7e96bcb7cca2f6c409909435325a615e2c1/packages/sdk/src/provider/initializeMobileProvider.ts#L122)
- [metamask-sdk/packages/sdk/src/provider/initializeMobileProvider.ts#return chainId](https://github.com/MetaMask/metamask-sdk/blob/23127c42357e93fa23968e769051ded8bcb9f718/packages/sdk/src/provider/initializeMobileProvider.ts#L193)

To avoid this error, we decided to override the `getChainId` function of the connector to return the first id in the chain list if the call throws an error.


## Fixing the Emission of `display_uri`
RainbowKit uses the `display_uri` event to display the QR code for wallet connection.
It starts listening to this event before connecting to the wallet, repeating the process at each connection attempt.
However, the MetaMask SDK only emits this event once, during the first connection attempt.
If the user closes the connection modal and tries to connect again, the QR code will not be displayed.

See the folowing call stack:

- [rainbowkit/packages/rainbowkit/src/components/ConnectOptions/DesktopOptions.tsx#selectWallet](https://github.com/EdouardBougon/rainbowkit/blob/497614b30db7e636b4e560f1b81f6a1315e13429/packages/rainbowkit/src/components/ConnectOptions/DesktopOptions.tsx#L149)
- [rainbowkit/packages/rainbowkit/src/components/ConnectOptions/DesktopOptions.tsx#onQrCode](https://github.com/EdouardBougon/rainbowkit/blob/497614b30db7e636b4e560f1b81f6a1315e13429/packages/rainbowkit/src/components/ConnectOptions/DesktopOptions.tsx#L131)
- [rainbowkit/packages/rainbowkit/src/wallets/useWalletConnectors.ts#getQrCodeUri](https://github.com/EdouardBougon/rainbowkit/blob/497614b30db7e636b4e560f1b81f6a1315e13429/packages/rainbowkit/src/wallets/useWalletConnectors.ts#L210)
- [rainbowkit/packages/rainbowkit/src/wallets/useWalletConnectors.ts#getWalletConnectUri](https://github.com/EdouardBougon/rainbowkit/blob/497614b30db7e636b4e560f1b81f6a1315e13429/packages/rainbowkit/src/wallets/useWalletConnectors.ts#L121) (Start listening to the display_uri event)
- [rainbowkit/packages/rainbowkit/src/components/ConnectOptions/DesktopOptions.tsx#connectToWallet](https://github.com/EdouardBougon/rainbowkit/blob/497614b30db7e636b4e560f1b81f6a1315e13429/packages/rainbowkit/src/components/ConnectOptions/DesktopOptions.tsx#L161)
- [wagmi/packages/connectors/src/metaMask.ts#connect](https://github.com/wevm/wagmi/blob/4e9493aa0fb2d7801040a4000e8c634eb0aba608/packages/connectors/src/metaMask.ts#L61)
- [metamask-sdk/packages/sdk/src/sdk.ts#connect](https://github.com/MetaMask/metamask-sdk/blob/23127c42357e93fa23968e769051ded8bcb9f718/packages/sdk/src/sdk.ts#L274)
- [metamask-sdk/packages/sdk/src/services/MetaMaskSDK/ConnectionManager/connect.ts#connect](https://github.com/MetaMask/metamask-sdk/blob/23127c42357e93fa23968e769051ded8bcb9f718/packages/sdk/src/services/MetaMaskSDK/ConnectionManager/connect.ts#L16)
- [metamask-sdk/packages/sdk/src/sdk.ts#init](https://github.com/MetaMask/metamask-sdk/blob/23127c42357e93fa23968e769051ded8bcb9f718/packages/sdk/src/sdk.ts#L266)
- [❌ metamask-sdk/packages/sdk/src/services/MetaMaskSDK/InitializerManager/initializeMetaMaskSDK.ts#initializeMetaMaskSDK](https://github.com/MetaMask/metamask-sdk/blob/23127c42357e93fa23968e769051ded8bcb9f718/packages/sdk/src/services/MetaMaskSDK/InitializerManager/initializeMetaMaskSDK.ts#L16) (If we already attempted to connect, the second attempt will stop here)
- [metamask-sdk/packages/sdk/src/services/MetaMaskSDK/InitializerManager/performSDKInitialization.ts#performSDKInitialization](https://github.com/MetaMask/metamask-sdk/blob/23127c42357e93fa23968e769051ded8bcb9f718/packages/sdk/src/services/MetaMaskSDK/InitializerManager/performSDKInitialization.ts#L41)
- [metamask-sdk/packages/sdk/src/services/RemoteConnection/RemoteConnection.ts#startConnection](https://github.com/MetaMask/metamask-sdk/blob/23127c42357e93fa23968e769051ded8bcb9f718/packages/sdk/src/services/RemoteConnection/RemoteConnection.ts#L154)
- [metamask-sdk/packages/sdk/src/services/RemoteConnection/ConnectionManager/startConnection.ts#startConnection](https://github.com/MetaMask/metamask-sdk/blob/23127c42357e93fa23968e769051ded8bcb9f718/packages/sdk/src/services/RemoteConnection/ConnectionManager/startConnection.ts#L26)
- [provider.emit('display_uri', qrcodeLink);](https://github.com/MetaMask/metamask-sdk/blob/23127c42357e93fa23968e769051ded8bcb9f718/packages/sdk/src/services/RemoteConnection/ConnectionManager/startConnection.ts#L112)

The ❌ mark where the second connection attempt will stop.

To resolve this, we added a specific condition in RainbowKit to get the displayUri content [here](https://github.com/EdouardBougon/rainbowkit/blob/497614b30db7e636b4e560f1b81f6a1315e13429/packages/rainbowkit/src/wallets/useWalletConnectors.ts#L103).
The `display_uri` value is cached in the connector and will be deleted if the connection is closed, and updated if the connector emit a new `display_uri` event.


## Exposed parameters
We decided only the folowing parameters are relevant to be exposed to the user:
- `infuraAPIKey`

We don't want that the user access to the modal content, or any other parameters that could be used to change the behavior of the connector.
Loading