Skip to content

Commit

Permalink
Document Expo & React Native SDK instructions (#1047)
Browse files Browse the repository at this point in the history
* Document Expo & React Native SDK instructions

* edits

* move RN before Expo
  • Loading branch information
alexandratran authored Dec 11, 2023
1 parent 4cbdad7 commit 63206d2
Showing 1 changed file with 186 additions and 100 deletions.
286 changes: 186 additions & 100 deletions wallet/how-to/connect/set-up-sdk/javascript/react-native.md
Original file line number Diff line number Diff line change
@@ -1,150 +1,236 @@
---
sidebar_label: React Native
sidebar_label: React Native and Expo
sidebar_position: 4
---

# Use MetaMask SDK with React Native
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

Import [MetaMask SDK](../../../../concepts/sdk/index.md) into your React Native dapp to enable your
users to easily connect to the MetaMask browser extension and MetaMask Mobile.
# Use MetaMask SDK with React Native and Expo

:::tip Example
See the [example React Native dapp](https://github.com/MetaMask/metamask-sdk/tree/main/packages/examples/reactNativeDemo)
in the JavaScript SDK GitHub repository for advanced use cases.
:::
Import [MetaMask SDK](../../../../concepts/sdk/index.md) into your React Native or Expo dapp to
enable your users to easily connect to the MetaMask browser extension and MetaMask Mobile.

## Prerequisites

- A [React Native](https://reactnative.dev/docs/0.71/getting-started) project set up with React Native version 0.71 or above
- [MetaMask Mobile](https://github.com/MetaMask/metamask-mobile) version 5.8.1 or above
- [Yarn](https://yarnpkg.com/getting-started/install) or
[npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)

## Steps

### 1. Install the SDK
### 1. Create a new project

:::info Coming soon
A `metamask-react-native-sdk` package that simplifies the installation of the SDK for React Native
dapps is coming soon.
:::
Create a new React Native or Expo project using the following commands:

Use [`rn-nodeify`](https://github.com/tradle/rn-nodeify) to install the SDK.
In your project directory, install `rn-nodeify`:
<Tabs>
<TabItem value="React Native">

```bash
yarn add --dev rn-nodeify
```
```bash
npx react-native@latest init MyProject
```

or
</TabItem>
<TabItem value="Expo">

```bash
npm i --dev rn-nodeify
```
```bash
npx create-expo-app devexpo --template
```

Install the `rn-nodeify` libraries:
</TabItem>
</Tabs>

```bash
yarn add react-native-crypto
yarn add react-native-randombytes
yarn add crypto
yarn add process
yarn add stream
yarn add events
```
### 2. Install the SDK

In your project's `package.json` file, insert the `rn-nodeify` command into the postinstall script:
Install the SDK and its dependencies using the following commands:

```json title="package.json"
"scripts": {
...,
"postinstall": "rn-nodeify --install 'crypto,process,stream,events' --hack"
}
```
<Tabs>
<TabItem value="React Native">

`rn-nodeify` creates a `shim.js` file in your project root directory.
Import it in the root file of your application:
```bash
npm install eciesjs @metamask/sdk-react [email protected] @react-native-async-storage/async-storage node-libs-react-native react-native-background-timer react-native-randombytes react-native-url-polyfill react-native-get-random-values
```

```bash
import './shim'
```
</TabItem>
<TabItem value="Expo">

Install `react-native-background-timer`:
```bash
npx expo install expo-crypto @metamask/sdk-react [email protected] @react-native-async-storage/async-storage node-libs-expo react-native-background-timer react-native-randombytes react-native-url-polyfill [email protected]
```

```bash
yarn add react-native-background-timer
</TabItem>
</Tabs>

cd ios && pod install && cd ..
```
### 3. Update the configuration file

Install MetaMask SDK:
If you're using Expo, run the following command to create a default Metro configuration file:

```bash
yarn add @metamask/sdk
npx expo customize metro.config.js
```

Run the postinstall script after everything is installed:
In React Native or Expo, update the default Metro configuration file to the following:

```bash
yarn postinstall
```
<Tabs>
<TabItem value="React Native">

```javascript title="metro.config.js"
const {
getDefaultConfig,
mergeConfig,
} = require("@react-native/metro-config");

const defaultConfig = getDefaultConfig(__dirname);

const config = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
resolver: {
extraNodeModules: {
...require("node-libs-react-native"),
},
},
};

module.exports = mergeConfig(defaultConfig, config);
```

</TabItem>
<TabItem value="Expo">

```javascript title="metro.config.js"
const config = getDefaultConfig(__dirname);

config.resolver.extraNodeModules = {
...require("node-libs-expo"),
};

config.transformer.getTransformOptions = async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
});

module.exports = config;
```

</TabItem>
</Tabs>

### 4. Add import statements

Add the following import statements to the React Native or Expo entry file:

Finally, install the necessary pods that come with the libraries:
<Tabs>
<TabItem value="React Native">

```javascript title="index.js or App.tsx"
import "node-libs-react-native/globals";
import "react-native-url-polyfill/auto";
import "react-native-get-random-values";
```

</TabItem>
<TabItem value="Expo">

```javascript title="App.tsx"
import "node-libs-expo/globals";
import "react-native-url-polyfill/auto";
import "react-native-get-random-values";
```

</TabItem>
</Tabs>

### 5. Prebuild the project

If you're using Expo, prebuild the project using the following command:

```bash
cd ios && pod install && cd ..
npx expo prebuild
```

### 2. Use the SDK
React Native doesn't require prebuilding.

### 6. Run the project

Run the React Native or Expo project on Android or iOS using the following commands:

<Tabs>
<TabItem value="React Native">

```bash
npx react-native run-android
npx react-native run-ios
```

</TabItem>
<TabItem value="Expo">

```bash
npx expo run:android
npx expo run:ios
```

</TabItem>
</Tabs>

Import, instantiate, and use the SDK by adding something similar to the following to your project script:
### 7. Use the SDK

Initialize and use the SDK in your React Native or Expo project using the `useSDK` hook.
The following code snippets demonstrate how to use the hook.

Import the hook:

```javascript
import MetaMaskSDK from '@metamask/sdk';
import { Linking } from 'react-native';
import BackgroundTimer from 'react-native-background-timer';

const MMSDK = new MetaMaskSDK({
openDeeplink: (link) => {
Linking.openURL(link); // Use React Native Linking method or another way of opening deeplinks.
},
timer: BackgroundTimer, // To keep the dapp alive once it goes to background.
dappMetadata: {
name: 'My dapp', // The name of your dapp.
url: 'https://mydapp.com', // The URL of your website.
},
});

const ethereum = MMSDK.getProvider();

const accounts = await ethereum.request({ method: 'eth_requestAccounts' });
import { useSDK } from "@metamask/sdk-react";
```

You can configure the SDK using any [options](../../../../reference/sdk-js-options.md) and call any
[provider API methods](../../../../reference/provider-api.md).
Always call [`eth_requestAccounts`](/wallet/reference/eth_requestaccounts) using
[`ethereum.request(args)`](../../../../reference/provider-api.md#windowethereumrequestargs) first,
since it prompts the installation or connection popup to appear.
Initialize the SDK in your main component:

:::note Important SDK options
- Use [`dappMetadata`](../../../../reference/sdk-js-options.md#dappmetadata) to display information
about your dapp in the MetaMask connection modal.
- Use [`modals`](../../../../reference/sdk-js-options.md#modals) to [customize the logic and UI of
the displayed modals](../../../display/custom-modals.md).
- Use [`infuraAPIKey`](../../../../reference/sdk-js-options.md#infuraapikey) to
[make read-only RPC requests](../../../use-3rd-party-integrations/js-infura-api.md) from your dapp.
:::
```javascript
const { connect, disconnect, account, chainId, ethereum } = useSDK();
```

You can use [EthersJS](https://docs.ethers.io/v5/getting-started/) with your React Native app:
Connect to MetaMask:

```javascript
const provider = new ethers.providers.Web3Provider(ethereum);
const connectWallet = async () => {
try {
await connect();
} catch (error) {
console.error("Failed to connect wallet:", error);
}
};
```

// Get the balance of an account (by address or ENS name, if supported by network).
const balance = await provider.getBalance(ethereum.selectedAddress);
Handle your dapp's state:

// Often you need to format the output to something more user-friendly,
// such as in ether (instead of wei).
const balanceInETH = ethers.utils.formatEther(balance);
// '0.182826475815887608'
```javascript
useEffect(() => {
// Use the 'account' and 'chainId' returned by 'useSDK'
if (account && chainId) {
// Handle account and network changes
}
}, [account, chainId]);
```

Disconnect from MetaMask:

```javascript
const disconnectWallet = async () => {
await disconnect();
};
```

## Examples

See the [example React Native dapp](https://github.com/MetaMask/metamask-sdk/tree/main/packages/examples/reactNativeDemo)
and the [example Expo dapp](https://github.com/MetaMask/metamask-sdk/tree/main/packages/examples/expo-demo)
in the JavaScript SDK GitHub repository for more detailed implementations.

0 comments on commit 63206d2

Please sign in to comment.