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 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 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 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
The backend API setup is the same for React and React Native. See the React guide for the backend endpoint code (Steps 1-3).
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.
Create Transfer Component
Now create the main transfer component that allows users to send USDC by email or phone:dynamicClient is set up with the ViemExtension:
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