We're going to build an app that you can use to send tokens from your wallet to another person's wallet, on devnet.
You will learn how to:
- Authorize your app with an SMS Mobile Wallet Adapter compatible wallet
- Reuse a prior wallet authorization over and over
- Sign and send transactions with an SMS Mobile Wallet Adapter compatible wallet
We'll build an app that features:
- A button to airdrop SOL to your wallet on devnet
- A readout of your wallet's current balance
- A QR code scanner you can use to get a recipient's address
Follow the “Installing Dependencies” instructions of the React Native docs to get a working copy of the Android SDK on your machine. You'll need this to compile the app and run it on an Android simulator or device.
As part of the Solana Mobile Stack SDK, you will find a ‘fake’ Mobile Wallet Adapter compliant wallet. Install it on your Android simulator or device.
- Get the Mobile Wallet Adapter SDK.
git clone git@github.com:solana-mobile/mobile-wallet-adapter.git
- Open the
android/
folder using Android Studio. - Choose ‘fakewallet’, choose your device or simulator, and press ‘run’ to install it.
Connect your device if you're using one, then:
yarn && yarn android
We'll make use of these three libraries from Solana Labs and Solana Mobile to prepare, sign, and send transactions on the network.
yarn add \
@solana-mobile/mobile-wallet-adapter-protocol \
@solana-mobile/mobile-wallet-adapter-protocol-web3js \
@solana/web3.js
Hermes is now the default JavaScript engine in React Native 0.70, but the Hermes transforms are not yet on by default. Enable them with this change to babel.config.js
.
module.exports = {
- presets: ['module:metro-react-native-babel-preset'],
+ presets: [
+ [
+ 'module:metro-react-native-babel-preset',
+ {unstable_transformProfile: 'hermes-stable'},
+ ],
+ ],
};
Certain of our dependencies require polyfills specifically for React Native. First install these dependencies.
yarn add \
react-native-get-random-values \
react-native-url-polyfill
@craftzdog/react-native-buffer \
react-native-quick-base64
Enable all of them in index.js
import 'react-native-get-random-values';
import 'react-native-url-polyfill/auto';
import {Buffer} from '@craftzdog/react-native-buffer';
global.Buffer = Buffer;
Mobile Wallet Adapter uses base64-encoded public keys, but libraries like @solana/web3.js
use base58-encoded public keys. In order to bridge the gap, install a conversion utility.
yarn add react-native-quick-base64
You can use this in your app like this:
import {toByteArray} from 'react-native-quick-base64';
import {PublicKey} from '@solana/web3.js';
// When authorizing a wallet...
const [{accounts}] = wallet.authorize(...);
const firstAccount = accounts[0];
// ...the public keys you receive are base64-encoded.
const base64PublicKey = firstAccount.pubkey;
// Convert them to byte arrays before using them with web3.js
const publicKeyByteArray = toByteArray(base64PublicKey);
const publicKey = new PublicKey(publicKeyByteArray);
You may want to save the address and authentication token of the currently authorized wallet so that you can reuse it between reloads of the app. Install a simple storage solution like this:
yarn add @react-native-async-storage/async-storage
You can use it like this:
import AsyncStorage from '@react-native-async-storage/async-storage';
// Store a string against some key.
await AsyncStorage.setItem('address', 'abc123');
// Then, some time later...
const storedAddress = await AsyncStorage.getItem('address');
Typing in a base58-encoded wallet address is tedious. Let's install a QR code scanner instead.
yarn add react-native-camera-kit
-
Enable the following app permissions in
android/src/main/AndroidManifest.xml
:<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
-
Open and edit
android/build.gradle
-
Add the
kotlin_version
tobuildscript.ext
buildscript { ext { kotlin_version = '1.7.0' } }
-
Add the Kotlin classpath to
buildscript.dependencies
dependencies { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") }
-
-
Open and edit
android/app/build.gradle
and add Kotlin importsapply plugin: "kotlin-android" apply plugin: "kotlin-android-extensions"
You can use it like this:
import {Camera, CameraType} from 'react-native-camera-kit';
<Camera
cameraType={CameraType.Back}
scanBarcode={true}
onReadCode={(event: any) => {
const codeContents = event.nativeEvent.codeStringValue;
console.log(codeContents);
}}
/>;
Read the documentation for React Native Camera Kit here.