This guide supports both React and React Native.
Overview
One of the biggest barriers to mainstream crypto adoption is the complexity of wallet addresses and the requirement that both parties must have wallets. This recipe shows you how to build a user-friendly USDC transfer system where users can send stablecoins to friends using familiar identifiers like email addresses or phone numbers—even if the recipient hasn’t signed up yet. Using Dynamic’s pregeneration feature, you can create wallets for recipients automatically when they’re sent funds. When recipients later sign up with that email or phone number, they’ll automatically receive their wallet with the funds already in it.What We’re Building
A React/React Native application that allows users to:- Send USDC to friends by entering their email address or phone number
- Automatically create wallets for recipients who don’t have one yet (pregeneration)
- Transfer USDC seamlessly without exposing wallet addresses to end users
- Enable recipients to claim their wallet and funds when they sign up later
Architecture
The solution uses a secure backend-to-backend pattern:- Backend API Endpoint: A secure backend endpoint queries Dynamic’s API with filters to find users by their email/phone verified credentials. The Dynamic API token is never exposed to the client.
- Frontend Lookup: The React/React Native app calls your backend API endpoint (not Dynamic’s API directly)
- Wallet Resolution: The backend extracts wallet addresses from the found user’s embedded wallets
- Transfer Component: A React/React Native component that looks up recipients via your backend API and executes USDC transfers
Prerequisites
- Sender must be a Dynamic user with a wallet linked (either embedded or external)
- Recipient can be anyone with an email address or phone number (they don’t need to have signed up yet)
- Backend server with Dynamic API token (the token must never be exposed to the client)
- Embedded wallets enabled in your Dynamic environment for pregeneration support
Step 1: Get Your Dynamic API Credentials
- Navigate to Dynamic Dashboard
- Copy your
Environment ID - Create a new API token

Step 2: Create User Lookup API Endpoint (existing users only)
First create a lookup endpoint that only searches for existing users by email or phone. We’ll rely on Dynamic’s publishedUser type instead of defining our own shape.
Environment Variables
Set up your environment variables:Step 3: Create Wallet Pregeneration Endpoint
Keep pregeneration in its own endpoint so it is clear, auditable, and can be called independently (for example, to pre-warm wallets in batches).Step 4: Create User Lookup Hook (React Query)
Create a custom hook that uses React Query to first try lookup, then fall back to pregeneration. Make sure your app is wrapped in aQueryClientProvider.
- React
- React Native
React
Step 5: Create Transfer Component
Now create the main transfer component that allows users to send USDC by email or phone:- React
- React Native
React
How Recipients Claim Their Wallets
When you send USDC to a friend who doesn’t have a wallet yet:- Pregeneration: A wallet is automatically created for them with the email/phone you provided
- Funds Arrive: The USDC is sent to that wallet address immediately
- Sign Up: When your friend signs up with Dynamic using the same email or phone number
- Automatic Claim: They automatically receive their pregenerated wallet with the funds already in it
Important Considerations
Security
- API Token Protection: Critical: Never expose your Dynamic API token in client-side code. All Dynamic API calls must happen on your backend server. The frontend should only call your backend API endpoints.
- Rate Limiting: Implement rate limiting on lookup endpoints to prevent abuse
- Authentication: Consider requiring authentication for lookup endpoints to prevent unauthorized access
- Validation: Always validate email/phone formats and wallet addresses on both frontend and backend
- Backend Security: Keep your backend API token secure using environment variables and never commit it to version control
Performance
- Rate limits (Dynamic):
/environments/:environmentId/usersfollows developer limits of 1500 requests/min per IP and 3000 requests/min per environment;/environments/:environmentId/users/embeddedWallets(pregeneration) is limited to 300 requests/min per IP. See rate limits. - Caching: Cache user lookups to reduce API calls and stay under limits
- Filtering: The API supports filtering - check the API reference for available filter parameters
User Experience
- Error Handling: Provide clear error messages for common issues
- Loading States: Show loading indicators during lookup and transfer
- Confirmation: Always show the recipient’s identifier before sending
- Transaction Status: Display transaction hashes and links to block explorers
Best Practices
- Error Handling: Handle cases where users don’t have EVM wallets or pregeneration fails
- Multiple Wallets: If a user has multiple EVM wallets, consider letting them choose or use the primary wallet
- Pregeneration: Always pregenerate wallets for new recipients so they can receive funds immediately
- Notifications: Consider sending email/SMS notifications to recipients when they receive USDC (especially for pregenerated wallets)
- Caching: Cache user lookups to improve performance and reduce API calls
- Network: Remember that USDC contract addresses differ by network. Update the
usdcAddressin your component based on the network. - User Communication: Inform recipients that they’ll need to sign up with the same email/phone to claim their funds