DEV Community

Cover image for Connecting React Native App to Crypto Wallet.
Oliver Kem
Oliver Kem

Posted on

Connecting React Native App to Crypto Wallet.

Hello everyone, πŸ‘‹, in this blog, I will show you how you can connect your React Native application to a wallet on your phone, you might be building an application where you need a user to pay with cryptocurrency in their wallet or you want a user to authenticate using their wallet address, well , you have come to the right place.

Prerequisites

  1. React Native knowledge
  2. Javascript

Let's begin, we start by creating a new react native application, I will be using Expo but feel free to switch to using the CLI, go to your terminal and create a React Native application

$ npx create-expo-app MyApp
Enter fullscreen mode Exit fullscreen mode

Follow the prompt if there is any then initialize a new application.
Then we open the installation in VSCODE.

$cd MyApp
$code .
Enter fullscreen mode Exit fullscreen mode

When you Open the Application, you'll be greeted by page showing all elements.

Let us change our App.js file and we add a few elements and styling, paste the following lines of code

import { StatusBar } from 'expo-status-bar';
import './global';
import { StyleSheet, ImageBackground,SafeAreaView, Platform,View } from 'react-native';
import React, { useState } from 'react';
import MainPage from './screens/MainPage';
import WalletConnectProvider from "@walletconnect/react-native-dapp";
import AsyncStorage from "@react-native-async-storage/async-storage";
const SCHEME_FROM_APP_JSON = "walletconnect-example";

export default function App() {
    let screen = <MainPage/>;
    return (
        <>
            <StatusBar style="dark" />
            <ImageBackground style={{flex:1}} imageStyle={{opacity: .5}} resizeMode='cover' source={require('./assets/background.jpg')}>
                <SafeAreaView style={styles.container}>
                    <WalletConnectProvider
                        redirectUrl={
                            Platform.OS === "web"
                            ? window.location.origin
                            : `${SCHEME_FROM_APP_JSON}://`
                        }
                        storageOptions={{
                            asyncStorage: AsyncStorage,
                        }}
                        >
                        <View style={styles.container}>
                            {/* <StatusBar style="auto" /> */}
                            {screen}
                            {/* <WalletConnectExperience functionStateHandler={functionStateHandler} /> */}
                        </View>
                    </WalletConnectProvider>
                </SafeAreaView>
            </ImageBackground>
        </>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
    },
    backgroundImage:{
        // opacity: .15,
        flex:1,
        // backgroundColor:'rgba(0,0,0,.5)'
    }
});

Enter fullscreen mode Exit fullscreen mode

With this, I have wrapped the main page with the WalletConnectProvider. We will see this later in action
Now let's create a components folder and then we create a component called Button.component.jsx. Inside the file, paste the following code.

import React from 'react';
import { StyleSheet, Text, View, Pressable } from 'react-native';
function Button({children,onPress, widthSet}) {
    return (
        <View style={[styles.buttonOuterContainer,{width: widthSet,}]}>
            <Pressable
                style={({ pressed }) =>
                    pressed
                        ? [styles.pressed, styles.button_Inner_container]
                        : styles.button_Inner_container
                }
                android_ripple={{ color: '#6CA9F9' }}
                onPress={onPress}
            >
                <Text style={styles.buttonText}>{children}</Text>
            </Pressable>
        </View>
    );
}
const styles = StyleSheet.create({
    button_Inner_container: {
        backgroundColor: '#4E97F5',

        paddingVertical: 16,
        paddingHorizontal: 16,
        elevation: 4,
    },
    buttonOuterContainer: {

        margin: 4,
        borderRadius: 1,
        overflow: "hidden",
    },
    buttonText: {
        color: "#fff",
        textAlign: "center",
    },
    pressed: {
        opacity: 0.75,
    },
});
export default Button;
Enter fullscreen mode Exit fullscreen mode

We have just added a button and styled it. Nothing fancy at all.
...
Now, let's create a folder called screens and the we add a page called MainPage.jsx, let us install a library

 $ npm install react-native-dropdown-picker
Enter fullscreen mode Exit fullscreen mode

Inside the mainpage, paste the following lines of code

import React,{useEffect} from 'react';
import { StyleSheet,TouchableOpacity, Text,FlatList, View, Dimensions, TextInput, ScrollView, Alert } from 'react-native';
import {Dropdown} from 'react-native-element-dropdown';
import { AntDesign } from '@expo/vector-icons';
import ButtonComponent from '../components/Button.component.jsx'
function MainPage() {
    const { height } = Dimensions.get('window');
    const connector = useWalletConnect();
    const [isFocus, setIsFocus] = React.useState(false);
    const [value, setValue] = React.useState({wallet:0, amount:0, receiver: ''});
    const [transactionHistory,setTransactionHistory] = React.useState([]);
    const [ownerAddress,setOwnerAddress] = React.useState('');




    return (
        <View style={{flex:1,marginTop:height*.09,position:'relative'}}>
            <View  style={{flexDirection:'row',alignItems:'center',justifyContent: 'space-between',marginHorizontal:7 }}>
                <View style={{flexDirection:'row', alignItems:'center'}}>
                    <Text style={styles.boldText}>Total Sent:</Text>
                    <Text style={styles.boldText}>0 BTC</Text>
                </View>
                <View style={{flexDirection:'row', alignItems:'center'}}>

                        <>
                          <Text style={styles.boldText}>Wallet Address</Text>
                             <ButtonComponent widthSet={'20%'} onPress={()=>{}} >Log out</ButtonComponent>
                       </>

                </View>
            </View>
            <Text style={[styles.boldText,{marginTop:height*.04, textAlign:'center'}]}> Send only 5 BTC per transaction</Text>

            <Dropdown
                style={[styles.dropdown, isFocus && { borderColor: '#000' }]}
                placeholderStyle={styles.placeholderStyle}
                selectedTextStyle={styles.selectedTextStyle}
                inputSearchStyle={styles.inputSearchStyle}
                iconStyle={styles.iconStyle}
                data={[
                    { label: "Blockchain", value: 1},
                    {label:"Trust Wallet",value: 2},
                    {label:"Binance",value: 3},
                ]}
                search
                maxHeight={300}
                labelField="label"
                valueField="value"
                placeholder={!isFocus ? 'Select Account' : '...'}
                searchPlaceholder="Search..."
                value={value.wallet}
                onFocus={() => setIsFocus(true)}
                onBlur={() => setIsFocus(false)}
                onChange={item => {
                    setValue({wallet: item.value});
                    setIsFocus(false);
                }}
                renderLeftIcon={() => (
                    <AntDesign style={styles.icon}
                        color={isFocus ? '#fff' : 'black'}
                        name="Safety"
                        size={20}
                    />
                )}
            />
            <View style={{marginTop:height*.04,alignItems:'center',flexDirection:'row'}}>
                <Text style={styles.boldText} >Receiver's Wallet:</Text>
                <TextInput keyboardType='twitter' 
                    style={[styles.textInput,{width:'70%'}]} 
                    placeholder="0.00000000" 

                />
            </View>
            <View style={{marginTop:height*.04,justifyContent:'space-evenly',alignItems:'center',flexDirection:'row'}}>
                <Text style={styles.boldText}>BTC Amount</Text>
                <TextInput keyboardType='number-pad' 
                    style={styles.textInput} 
                    placeholder="0.00000000" 

                />
                <Button widthSet={'20%'} label={'Send'}/>
            </View>
            <View style={{marginTop:height*.04,marginHorizontal:height*.04}}>
                <View style={{flexDirection:'row', justifyContent:'space-between',borderBottomWidth:1,paddingVertical:10}}>
                    <Text style={styles.boldText}>History</Text>
                    <Text style={styles.boldText}>Clear</Text>
                </View>
                <ScrollView style={{height: height*.2}}>
                    <FlatList
                        data={transactionHistory}
                        renderItem={({ item }) => (
                            <View style={{flexDirection:'row',justifyContent:'space-between',paddingVertical:10}}>
                                <Text style={styles.normalText}>{item.date}</Text>
                                <Text style={styles.normalText}>{item.amount}</Text>
                            </View>
                        )}
                        keyExtractor={item => item.id}
                    />
                </ScrollView>
            </View>
            <View style={{position:'absolute',bottom:30}}>
                <Text style={[styles.boldText,{textAlign:'center',fontSize:20}]}>Need to Know</Text>
                <Text style={styles.normalText}>1. Transactions will get 6 confirmations on the Blockchain</Text>
                <Text style={styles.normalText}>2. Transactions stays for only 45 days before becoming invalid</Text>
                <Text style={styles.normalText}>3. Transactions takes 20-30mins</Text>
            </View>
        </View>
    );
}
const styles = StyleSheet.create({
    rowContainer: {
        backgroundColor: '#4E97F5',
    },
    textInput:{
        borderBottomWidth:.5,
        // ,
        // paddingHorizontal:10,
        // paddingVertical: 16,
        paddingHorizontal: 16,
    },
    boldText:{
        fontWeight:'bold',
        fontSize:16, 
    },
    normalText:{
        fontSize:16,
    },
    icon: {
        marginRight: 5,
    },
    placeholderStyle: {
        fontSize: 16,
    },
    selectedTextStyle: {
        fontSize: 16,
    },
    iconStyle: {
        width: 20,
        height: 20,
    },
    inputSearchStyle: {
        height: 40,
        fontSize: 16,
    },
    button: {
        backgroundColor: "#5A45FF",
        color: "#FFFFFF",
        borderRadius: 2,
        paddingHorizontal: 16,
        paddingVertical: 12,
    },
    text: {
        color: "#FFFFFF",
        fontSize: 16,
        fontWeight: "600",
    },
    dropdown: {
        height: 50,
        borderColor: '#000',
        borderBottomWidth: 0.5,
        paddingHorizontal: 8,
        marginVertical: 20,
    },
});
export default MainPage;
Enter fullscreen mode Exit fullscreen mode

When you implement this, you will get a nice design as shown below.

MainPage
//=====================image===========================//
Now, let us install a couple of dependencies

npx expo install @react-native-async-storage/async-storage @walletconnect/client @walletconnect/react-native-dapp

Enter fullscreen mode Exit fullscreen mode

After you have done this we do this

npm install react-native-get-random-values@1.8.0 react-native-randombytes@3.6.1 react-native-crypto@2.2.0
Enter fullscreen mode Exit fullscreen mode

After successfully installing this, we need to do a small thing. In the package.json file, let's add a script to be executed.

    "postinstall": "rn-nodeify --hack --install process,crypto,events,constant,console,stream,url,util"

Enter fullscreen mode Exit fullscreen mode

This is very essential because the

`@wallectconnect/react-native-dapp needs crypto module which is only native to NodeJS and not React Native, running this will include it to your application.

Now let's finish up on the frontend functionality by adding the following functions



    const connectWallet =() => {
        return connector.connect();
    };
    const killSession =() => {
        setValue({wallet:0});

        return connector.killSession();
    };
    const sendButtonHandler = () => {
        console.log('Pressed');
        console.log('Value is: ',value)
        if (value.amount <5 && value.amount && value.receiver && value.wallet && connector.connected && ownerAddress) {
            Alert.alert('Warning!!','Are you sure you want to send this?',[
                {
                    text:'No',
                    onPress:() => {
                        console.log('No Pressed');
                    },
                    style:'cancel'
                },
                {
                    text:'Yes',
                    onPress:() => {
                        console.log('Yes Pressed');

                    },
                    style:'destructive'
                }
            ])
            return;
        }
        Alert.alert('Error','Please fill all the fields correctly');
    };
    function connectButtonHandler(){
        console.log('Pressed',value.wallet)
        if(value.wallet===2){
            connectWallet();
        }
    }
    useEffect(() => {
        if(connector.connected){
            setOwnerAddress(connector.accounts[0]);
        }
    }, [connector.connected]);
    function Button({ onPress, label }) {
        return (
            <TouchableOpacity onPress={onPress} style={styles.button}>
                <Text style={styles.text}>{label}</Text>
            </TouchableOpacity>
        );
    }
    useEffect(() => {
        connectButtonHandler();
    }, [value.wallet]);


Enter fullscreen mode Exit fullscreen mode

Now let we will be binding this to their respective buttons. The final code in the

Mainpage.jsx
is like this
Final Code

Top comments (0)