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

# Quickstart

Get up and running with MoonKey in minutes. This guide walks you through authenticating users, creating embedded wallets, and executing blockchain transactions.

## Prerequisites

Before starting, make sure you've completed the [Setup guide](/get-started/frontend-sdks/react/setup) and have the `MoonKeyProvider` configured in your application.

## Step 1: Authenticate users with email

MoonKey makes authentication simple with email-based one-time passwords (OTPs). While this guide focuses on email authentication, MoonKey supports multiple methods including OAuth providers, wallet signatures, and WebAuthn.

<Tip>
  Want to explore other authentication options? Check out our [Authentication methods](/methods/overview) documentation to learn about social logins, passkeys, and Web3 wallet authentication.
</Tip>

### Using the email authentication hook

The `useLoginWithEmail` hook provides everything you need to implement email OTP authentication:

```tsx theme={null}
import { useLoginWithEmail } from '@moon-key/react-auth';

function LoginComponent() {
  const { sendCode, loginWithCode } = useLoginWithEmail();
  
  // Use these methods to authenticate your user
}
```

<Info>
  Make sure your component is wrapped by `MoonKeyProvider` to use MoonKey hooks. See the [Setup guide](/get-started/frontend-sdks/react/setup) for details.
</Info>

### Building a complete login flow

Here's a complete example showing how to collect an email, send an OTP, and authenticate the user:

```tsx theme={null}
import { useState } from 'react';
import { useLoginWithEmail } from '@moon-key/react-auth';

export default function EmailLogin() {
  const [email, setEmail] = useState('');
  const [otp, setOtp] = useState('');
  const [codeSent, setCodeSent] = useState(false);
  const { sendCode, loginWithCode, state } = useLoginWithEmail();

  const handleSendCode = async () => {
    try {
      await sendCode({ email });
      setCodeSent(true);
    } catch (error) {
      console.error('Failed to send code:', error);
    }
  };

  const handleLogin = async () => {
    try {
      await loginWithCode({ code: otp });
      // User is now authenticated!
    } catch (error) {
      console.error('Failed to login:', error);
    }
  };

  if (!codeSent) {
    return (
      <div>
        <h2>Log in with Email</h2>
        <input
          type="email"
          placeholder="Enter your email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
        <button onClick={handleSendCode} disabled={!email || state === 'sending'}>
          {state === 'sending' ? 'Sending...' : 'Send Code'}
        </button>
      </div>
    );
  }

  return (
    <div>
      <h2>Enter your code</h2>
      <p>We sent a 6-digit code to {email}</p>
      <input
        type="text"
        placeholder="000000"
        value={otp}
        onChange={(e) => setOtp(e.target.value)}
        maxLength={6}
      />
      <button onClick={handleLogin} disabled={otp.length !== 6 || state === 'logging-in'}>
        {state === 'logging-in' ? 'Logging in...' : 'Verify & Login'}
      </button>
      <button onClick={() => setCodeSent(false)}>Change email</button>
    </div>
  );
}
```

The OTP is valid for 10 minutes. If it expires, users can request a new code by re-entering their email.

## Step 2: Create embedded wallets

MoonKey can automatically create self-custodial wallets for your users during the authentication flow. Configure this in your `MoonKeyProvider`:

```tsx theme={null}
<MoonKeyProvider
  publishableKey="your_publishable_key"
  config={{
    embeddedWallets: {
      createOnLogin: 'always' // Creates a wallet for every authenticated user
    }
  }}
>
  {children}
</MoonKeyProvider>
```

**Wallet creation options:**

* `'always'` — Automatically create a wallet for every user upon login
* `'none'` — Disable automatic wallet creation (create manually when needed)

<Info>
  MoonKey supports embedded wallet creation on both **Ethereum** (and all EVM chains) and **Solana**. Choose your blockchain when importing the provider.
</Info>

### Manual wallet creation

Alternatively, you can create wallets on-demand when users need them:

```tsx theme={null}
import { useCreateWallet } from '@moon-key/react-auth/ethereum';

function CreateWalletButton() {
  const { createWallet } = useCreateWallet();

  const handleCreateWallet = async () => {
    const wallet = await createWallet();
    console.log('Wallet created:', wallet.address);
  };

  return <button onClick={handleCreateWallet}>Create Wallet</button>;
}
```

## Step 3: Send transactions

Once users have embedded wallets, your app can prompt them to sign and send blockchain transactions.

<Tabs>
  <Tab title="Ethereum">
    Use the `useSendTransaction` hook to send transactions on Ethereum and EVM-compatible chains:

    ```tsx theme={null}
    import { useSendTransaction } from '@moon-key/react-auth/ethereum';

    export default function SendEthButton() {
      const { sendTransaction } = useSendTransaction();

      const handleSend = async () => {
        try {
          const txHash = await sendTransaction({
            to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
            value: '1000000000000000', // 0.001 ETH in wei
          });
          console.log('Transaction sent:', txHash);
        } catch (error) {
          console.error('Transaction failed:', error);
        }
      };

      return <button onClick={handleSend}>Send 0.001 ETH</button>;
    }
    ```
  </Tab>

  <Tab title="Solana">
    Use the `useSendTransaction` hook to send transactions on Solana:

    ```tsx theme={null}
    import { useSendTransaction } from '@moon-key/react-auth/solana';
    import { 
      Connection, 
      Transaction, 
      SystemProgram, 
      PublicKey,
      LAMPORTS_PER_SOL 
    } from '@solana/web3.js';

    export default function SendSolButton() {
      const { sendTransaction } = useSendTransaction();
      const connection = new Connection('https://api.mainnet-beta.solana.com');

      const handleSend = async () => {
        try {
          // Create a transfer transaction
          const transaction = new Transaction().add(
            SystemProgram.transfer({
              fromPubkey: userWallet.publicKey,
              toPubkey: new PublicKey('RECIPIENT_ADDRESS_HERE'),
              lamports: 0.01 * LAMPORTS_PER_SOL // 0.01 SOL
            })
          );

          const signature = await sendTransaction({
            transaction,
            connection
          });

          console.log('Transaction sent:', signature);
        } catch (error) {
          console.error('Transaction failed:', error);
        }
      };

      return <button onClick={handleSend}>Send 0.01 SOL</button>;
    }
    ```
  </Tab>
</Tabs>

## Accessing user data

After authentication, access user information with the `useMoonKey` hook:

```tsx theme={null}
import { useMoonKey } from '@moon-key/react-auth';

function UserProfile() {
  const { user, isAuthenticated } = useMoonKey();

  if (!isAuthenticated) {
    return <p>Please log in</p>;
  }

  return (
    <div>
      <h2>Welcome!</h2>
      <p>Email: {user?.email?.address}</p>
      <p>User ID: {user?.id}</p>
      <p>Wallet: {user?.wallet?.address}</p>
    </div>
  );
}
```

## Handling logout

Allow users to log out and clear their session:

```tsx theme={null}
import { useLogout } from '@moon-key/react-auth';

function LogoutButton() {
  const { logout } = useLogout();

  return <button onClick={logout}>Log Out</button>;
}
```

## Troubleshooting

### "User is not authenticated" error

Make sure you're checking the `isAuthenticated` state before attempting wallet operations:

```tsx theme={null}
const { isAuthenticated } = useMoonKey();

if (!isAuthenticated) {
  return <p>Please log in first</p>;
}
```

### Transactions failing

Common reasons transactions fail:

* Insufficient balance in the wallet
* Invalid recipient address
* Network congestion or RPC issues
* User rejected the transaction

Always wrap transaction calls in try-catch blocks to handle errors gracefully.

### Hook errors

If you see "Hook can only be used inside MoonKeyProvider", ensure:

1. Your component is wrapped by `MoonKeyProvider`
2. You're importing from the correct package (`@moon-key/react-auth/ethereum` or `@moon-key/react-auth/solana`)
3. The provider is mounted before components using hooks
