> ## Documentation Index
> Fetch the complete documentation index at: https://docs.crossmint.com/llms.txt
> Use this file to discover all available pages before exploring further.

# React Native

> Create user wallets from your frontend in under 5 minutes

<Warning>
  **You are viewing docs for the previous version of the Wallets SDK.** We recommend upgrading to V1.
  See the [updated version of this page](/wallets/quickstarts/react-native) or the [V1 migration guide](/wallets/guides/migrate-to-v1).
</Warning>

<CardGroup cols={2}>
  <Snippet file="before-you-start.mdx" />

  <Card title="Expo Wallets Quickstart" icon="github" iconType="duotone" href="https://github.com/Crossmint/wallets-expo-quickstart">
    See a full working example.
  </Card>
</CardGroup>

<Steps>
  <Step title="Install the SDK">
    Run the following command to install the SDK:

    <Snippet file="client-sdk-react-native-ui-installation-cmd.mdx" />
  </Step>

  <Step title="Add the Crossmint providers to your app">
    Add the necessary Crossmint providers to your app. This example uses [Crossmint Auth](/authentication/introduction)
    but you can use [any authentication provider of your choice](/wallets/v0/guides/bring-your-own-auth).

    With the current setup, a wallet will be created automatically on login.

    See all supported chains [here](/introduction/supported-chains).

    ```tsx providers.tsx theme={null}
    import {
        CrossmintAuthProvider,
        CrossmintProvider,
        CrossmintWalletProvider,
    } from "@crossmint/client-sdk-react-native-ui";

    type ProvidersProps = {
        children: React.ReactNode;
    };

    export default function CrossmintProviders({ children }: ProvidersProps) {

        return (
            <CrossmintProvider apiKey={"<your-client-api-key>"}>
                <CrossmintAuthProvider>
                    <CrossmintWalletProvider
                        createOnLogin={{
                            chain: "<your-chain>",
                            signer: {
                                type: "<signer-type>",
                            }
                        }}
                    >
                        {children}
                    </CrossmintWalletProvider>
                </CrossmintAuthProvider>
            </CrossmintProvider>
        );
    }
    ```

    For detailed configuration options, see the [React Native SDK Reference](/sdk-reference/wallets/v0/react-native/providers#crossmintwalletprovider).
  </Step>

  <Step title="Allow users to login and logout and access their wallet">
    Crossmint Auth in React Native is headless. You will need to implement your own login and logout buttons.

    ```tsx index.tsx theme={null}
    import React, { useEffect, useState } from "react";
    import {
        View,
        Text,
        TextInput,
        TouchableOpacity,
        ActivityIndicator,
        Alert,
    } from "react-native";
    import {
        useCrossmintAuth,
        useWallet,
    } from "@crossmint/client-sdk-react-native-ui";
    import * as Linking from "expo-linking";

    export default function Index() {
        const {
            loginWithOAuth,
            createAuthSession,
            user,
            crossmintAuth,
            logout,
            status,
        } = useCrossmintAuth();
        const { wallet } = useWallet();

        // Login state
        const [email, setEmail] = useState("");
        const [emailId, setEmailId] = useState("");
        const [otpSent, setOtpSent] = useState(false);
        const [otp, setOtp] = useState("");
        const [isPending, setIsPending] = useState(false);

        // Handle OAuth callback
        useEffect(() => {
            const url = Linking.useURL();
            if (url != null) {
                createAuthSession(url);
            }
        }, [createAuthSession]);

        // Login functions
        const sendOtp = async () => {
            if (!email.trim()) {
                Alert.alert("Error", "Please enter a valid email address");
                return;
            }

            setIsPending(true);
            try {
                const res = await crossmintAuth?.sendEmailOtp(email);
                setEmailId(res.emailId);
                setOtpSent(true);
            } catch (error) {
                Alert.alert("Error", "Failed to send OTP. Please try again.");
            } finally {
                setIsPending(false);
            }
        };

        const verifyOtp = async () => {
            if (!otp.trim()) {
                Alert.alert("Error", "Please enter the OTP code");
                return;
            }

            setIsPending(true);
            try {
                const oneTimeSecret = await crossmintAuth?.confirmEmailOtp(
                    email,
                    emailId,
                    otp
                );
                await createAuthSession(oneTimeSecret);
            } catch (error) {
                Alert.alert("Error", "Invalid OTP code. Please try again.");
            } finally {
                setIsPending(false);
            }
        };

        const handleLogout = async () => {
            try {
                logout();
                // Reset login state
                setEmail("");
                setEmailId("");
                setOtpSent(false);
                setOtp("");
            } catch (error) {
                Alert.alert("Error", "Failed to logout. Please try again.");
            }
        };

        // Loading state
        if (status === "initializing") {
            return (
                <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
                    <ActivityIndicator size="large" />
                    <Text>Initializing...</Text>
                </View>
            );
        }

        // Login screen
        if (status === "logged-out") {
            return (
                <View style={{ flex: 1, padding: 20, justifyContent: "center" }}>
                    <Text style={{ fontSize: 24, marginBottom: 20, textAlign: "center" }}>
                        Login
                    </Text>

                    <TextInput
                        style={{ borderWidth: 1, padding: 10, marginBottom: 10 }}
                        placeholder="Enter your email"
                        value={email}
                        onChangeText={setEmail}
                        editable={!otpSent}
                    />

                    {!otpSent ? (
                        <TouchableOpacity
                            style={{
                                backgroundColor: "#05b959",
                                padding: 15,
                                alignItems: "center",
                            }}
                            onPress={sendOtp}
                            disabled={isPending}
                        >
                            {isPending ? (
                                <ActivityIndicator color="#fff" size="small" />
                                ) : (
                                <Text style={{ color: "#fff" }}>Send OTP</Text>
                            )}
                        </TouchableOpacity>
                        ) : (
                        <>
                            <TextInput
                                style={{ borderWidth: 1, padding: 10, marginBottom: 10 }}
                                placeholder="Enter OTP code"
                                value={otp}
                                onChangeText={setOtp}
                            />
                            <TouchableOpacity
                                style={{
                                    backgroundColor: "#05b959",
                                    padding: 15,
                                    alignItems: "center",
                                    marginBottom: 10,
                                }}
                                onPress={verifyOtp}
                                disabled={isPending}
                            >
                                {isPending ? (
                                    <ActivityIndicator color="#fff" size="small" />
                                ) : (
                                    <Text style={{ color: "#fff" }}>Verify OTP</Text>
                                )}
                            </TouchableOpacity>
                            <TouchableOpacity
                                style={{
                                    backgroundColor: "#ccc",
                                    padding: 15,
                                    alignItems: "center",
                                }}
                                onPress={() => setOtpSent(false)}
                                disabled={isPending}
                            >
                                <Text>Back</Text>
                            </TouchableOpacity>
                        </>
                    )}

                    <View style={{ marginVertical: 20 }}>
                        <Text style={{ textAlign: "center", marginBottom: 10 }}>OR</Text>
                        <TouchableOpacity
                            style={{
                                backgroundColor: "#4285f4",
                                padding: 15,
                                alignItems: "center",
                            }}
                            onPress={() => loginWithOAuth("google")}
                        >
                            <Text style={{ color: "#fff" }}>Sign in with Google</Text>
                        </TouchableOpacity>
                    </View>
                </View>
            );
        }

        // Main app screen (logged in)
        return (
            <View style={{ flex: 1, padding: 20 }}>
                <View
                    style={{
                        flexDirection: "row",
                        justifyContent: "space-between",
                        marginBottom: 20,
                    }}
                >
                    <Text style={{ fontSize: 20 }}>Welcome!</Text>
                    <TouchableOpacity onPress={handleLogout}>
                        <Text style={{ color: "red" }}>Logout</Text>
                    </TouchableOpacity>
                </View>

                <View style={{ marginBottom: 20 }}>
                    <Text style={{ fontSize: 16, marginBottom: 5 }}>User Info:</Text>
                    <Text>Email: {user?.email}</Text>
                    <Text>User ID: {user?.id}</Text>
                </View>

                {wallet && (
                    <View style={{ marginBottom: 20 }}>
                        <Text style={{ fontSize: 16, marginBottom: 5 }}>Wallet Info:</Text>
                        <Text>Address: {wallet.address}</Text>
                    </View>
                )}

                <View>
                    <Text style={{ fontSize: 16, marginBottom: 10 }}>App Content:</Text>
                    <Text>You are now logged in and can access your wallet!</Text>
                </View>
            </View>
        );
    }

    ```
  </Step>
</Steps>

## Launching in Production

For production, some changes are required:

1. Create a developer account on the [production console](https://www.crossmint.com/console)
2. Create a production client API key on the [API Keys](https://www.crossmint.com/console/projects/apiKeys) page with the API scopes `users.create`, `users.read`, `wallets.read`, `wallets.create`, `wallets:transactions.create`, `wallets:transactions.sign`, `wallets:balance.read`, `wallets.fund`
3. Replace your test API key with the production key
4. **Use your own authentication provider**: For production applications, Crossmint recommends using [third-party authentication](/wallets/v0/guides/bring-your-own-auth) with providers like Auth0, Firebase, or Supabase, rather than Crossmint Auth. Configure JWT authentication in the [Crossmint Console](https://www.crossmint.com/console/projects/apiKeys) under API Keys > JWT Authentication.

## Learn More

<CardGroup cols={3}>
  <Card title="Check Balances" icon="money-bill-transfer" iconType="duotone" href="/wallets/v0/guides/check-balances">
    Check the balance of a wallet.
  </Card>

  <Card title="Transfer Tokens" icon="coins" iconType="duotone" color="#1A5785" href="/wallets/v0/guides/transfer-tokens">
    Send tokens between wallets.
  </Card>

  <Card title="Operational Signers" icon="key" iconType="duotone" color="#2156B9" href="/wallets/v0/guides/signers/registering-a-signer">
    Register operational signers on a wallet.
  </Card>
</CardGroup>

## Other Links

<CardGroup cols={2}>
  <Card title="API Reference" icon="terminal" color="#B56710" href="/api-reference/wallets/create-wallet">
    Deep dive into API reference docs.
  </Card>

  <Card title="Talk to an expert" icon="message" iconType="duotone" color="#ADD8E6" href="https://www.crossmint.com/contact/sales">
    Contact our sales team for support.
  </Card>
</CardGroup>
