The MoonPay module provides seamless cryptocurrency purchasing capabilities directly within your app. Users can buy crypto using credit cards, debit cards, Apple Pay, and other payment methods through MoonPay’s trusted platform.
Core Functionalities
Crypto On-Ramp Purchase cryptocurrencies directly using various payment methods with automatic wallet integration
Wallet Integration Automatically populates the user’s connected wallet address as the destination for purchases
Customizable Widget Configurable MoonPay widget supporting both sandbox and production environments
Balance Management View wallet balances and seamlessly navigate to purchase flows when funds are needed
Installation & Setup
Install MoonPay SDK
The module uses the official MoonPay React Native SDK: npm install @moonpay/react-native-moonpay-sdk
Configure API Key
Add your MoonPay API key to .env.local
: MOONPAY_API_KEY = pk_test_your_api_key_here
# For production: pk_live_your_production_key
Import Components
Import the components you need: import {
MoonPayWidget ,
OnrampScreen ,
WalletScreen
} from '@/modules/moonpay' ;
API Keys : Use pk_test_
prefixed keys for testing and pk_live_
for production. The module automatically detects the environment.
Module Architecture
src/modules/moonpay/
├── components/ # UI components
│ └── MoonPayWidget/ # Core MoonPay WebView wrapper
├── screens/ # Complete screen implementations
├── services/ # MoonPay configuration and utilities
├── types/ # TypeScript definitions
└── utils/ # Helper functions
Core Components
Quick Start Example
Basic Integration
Custom Widget Implementation
Navigation Integration
import { OnrampScreen } from '@/modules/moonpay' ;
import { useWallet } from '@/modules/wallet-providers' ;
function BuyCryptoFlow () {
const { wallet } = useWallet ();
if ( ! wallet ) {
return (
< View style = {styles. container } >
< Text > Please connect your wallet first </ Text >
</ View >
);
}
return (
< View style = {styles. container } >
< Text style = {styles. title } > Buy Cryptocurrency </ Text >
< Text style = {styles. subtitle } >
Funds will be sent to : { wallet . address }
</ Text >
< OnrampScreen />
</ View >
);
}
MoonPay Service Configuration
The moonpayService.ts
provides configuration and validation utilities:
import { createMoonPayService } from '@/modules/moonpay' ;
// Create MoonPay service instance
const moonPayService = createMoonPayService ({
apiKey: process . env . MOONPAY_API_KEY ,
environment: 'sandbox' , // or 'production'
});
// Validate configuration
const isValid = moonPayService . validateConfig ();
if ( ! isValid ) {
console . error ( 'MoonPay configuration is invalid' );
}
// Get widget URL (if needed for custom implementations)
const widgetUrl = moonPayService . getWidgetUrl ({
walletAddress: userWallet . address ,
currencyCode: 'SOL' ,
baseCurrencyCode: 'USD' ,
});
Utility Functions
formatWalletAddress(address)
- Shortens wallet addresses for displayimport { formatWalletAddress } from '@/modules/moonpay/utils' ;
const address = '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM' ;
const formatted = formatWalletAddress ( address );
// Returns: "9WzD...AWWM"
parseErrorMessage(error)
- Converts raw errors to user-friendly messagesimport { parseErrorMessage } from '@/modules/moonpay/utils' ;
try {
// MoonPay operation
} catch ( error ) {
const userMessage = parseErrorMessage ( error );
Alert . alert ( 'Purchase Failed' , userMessage );
}
Show Environment Detection
getEnvironmentFromConfig(apiKey)
- Automatically detects sandbox vs productionimport { getEnvironmentFromConfig } from '@/modules/moonpay/utils' ;
const environment = getEnvironmentFromConfig ( process . env . MOONPAY_API_KEY );
// Returns: 'sandbox' for pk_test_ keys, 'production' for pk_live_ keys
Advanced Usage Patterns
Custom Purchase Flow
function CustomPurchaseFlow () {
const { wallet } = useWallet ();
const [ purchaseAmount , setPurchaseAmount ] = useState ( '' );
const [ selectedCurrency , setSelectedCurrency ] = useState ( 'SOL' );
const initiateCustomPurchase = () => {
// Custom logic before showing MoonPay widget
analytics . track ( 'purchase_initiated' , {
amount: purchaseAmount ,
currency: selectedCurrency ,
wallet: wallet . address
});
// Show MoonPay widget with pre-filled values
navigation . navigate ( 'OnrampScreen' , {
defaultAmount: purchaseAmount ,
defaultCurrency: selectedCurrency
});
};
return (
< View >
< TextInput
value = { purchaseAmount }
onChangeText = { setPurchaseAmount }
placeholder = "Amount to purchase"
keyboardType = "numeric"
/>
< Picker
selectedValue = { selectedCurrency }
onValueChange = { setSelectedCurrency }
>
< Picker . Item label = "Solana (SOL)" value = "SOL" />
< Picker . Item label = "USD Coin (USDC)" value = "USDC" />
</ Picker >
< Button
title = "Buy Crypto"
onPress = { initiateCustomPurchase }
/>
</ View >
);
}
Transaction Status Tracking
function useMoonPayTransactionStatus () {
const [ transactions , setTransactions ] = useState ([]);
const [ loading , setLoading ] = useState ( false );
const trackTransaction = async ( transactionId ) => {
setLoading ( true );
try {
// Note: This would require backend integration with MoonPay's API
const status = await fetch ( `/api/moonpay/transaction/ ${ transactionId } ` );
const data = await status . json ();
setTransactions ( prev =>
prev . map ( tx =>
tx . id === transactionId
? { ... tx , status: data . status }
: tx
)
);
} catch ( error ) {
console . error ( 'Failed to track transaction:' , error );
} finally {
setLoading ( false );
}
};
return { transactions , trackTransaction , loading };
}
Balance-Based Recommendations
function BalanceBasedOnramp () {
const { wallet } = useWallet ();
const { balance } = useBalance ( wallet ?. address );
const [ showRecommendation , setShowRecommendation ] = useState ( false );
useEffect (() => {
// Show purchase recommendation if balance is low
if ( balance < 0.1 ) { // Less than 0.1 SOL
setShowRecommendation ( true );
}
}, [ balance ]);
if ( ! showRecommendation ) return null ;
return (
< Card style = {styles. recommendationCard } >
< Text style = {styles. recommendationTitle } > Low Balance Detected </ Text >
< Text style = {styles. recommendationText } >
Your SOL balance is low ({balance.toFixed( 4 ) } SOL ).
Consider adding funds to cover transaction fees .
</ Text >
< Button
title = "Add Funds"
onPress = {() => navigation.navigate( 'OnrampScreen' )}
/>
<TouchableOpacity onPress={() => setShowRecommendation(false)}>
<Text style={styles.dismissText}>Dismiss</Text>
</TouchableOpacity>
</Card>
);
}
Integration with Other Modules
Combined Workflow Example
import { useWallet } from '@/modules/wallet-providers' ;
import { useFetchTokens } from '@/modules/data-module' ;
import { useSwap } from '@/modules/swap' ;
import { MoonPayWidget } from '@/modules/moonpay' ;
function BuyAndSwapFlow () {
const { wallet } = useWallet ();
const { refetch : refetchBalance } = useFetchTokens ( wallet ?. address );
const { executeSwap } = useSwap ();
const [ purchaseComplete , setPurchaseComplete ] = useState ( false );
const handlePurchaseComplete = async () => {
setPurchaseComplete ( true );
// Refresh balance after purchase
await refetchBalance ();
// Optional: Auto-swap purchased SOL to another token
const shouldSwap = await askUserForSwap ();
if ( shouldSwap ) {
navigation . navigate ( 'SwapScreen' , {
inputToken: 'SOL' ,
outputToken: 'USDC'
});
}
};
return (
< View >
{! purchaseComplete ? (
< MoonPayWidget
apiKey = {process.env. MOONPAY_API_KEY }
environment = "production"
onOpen = { handlePurchaseComplete }
/>
) : (
< PurchaseSuccessScreen onContinue = {() => navigation.goBack()} />
)}
</ View >
);
}
Environment Configuration
# .env.local for development
MOONPAY_API_KEY = pk_test_your_sandbox_key_here
Uses sandbox environment automatically
Test transactions don’t involve real money
Full widget functionality for testing
Error Handling & Troubleshooting
Widget Not Loading
Verify MOONPAY_API_KEY
is correctly set
Check internet connectivity
Ensure API key has proper permissions
Payment Failures
Card verification issues
Insufficient funds
Geographic restrictions
KYC requirements not met
Network Errors
Backend connectivity issues
Solana network congestion
Invalid wallet addresses
function RobustMoonPayWidget () {
const [ error , setError ] = useState ( null );
const [ retryCount , setRetryCount ] = useState ( 0 );
const maxRetries = 3 ;
const handleError = ( err ) => {
console . error ( 'MoonPay error:' , err );
setError ( parseErrorMessage ( err ));
};
const handleRetry = () => {
if ( retryCount < maxRetries ) {
setRetryCount ( prev => prev + 1 );
setError ( null );
} else {
Alert . alert (
'Connection Failed' ,
'Please check your internet connection and try again later.'
);
}
};
return (
< View >
{ error ? (
< ErrorDisplay
message = { error }
onRetry = {retryCount < maxRetries ? handleRetry : null }
/>
) : (
< MoonPayWidget
apiKey = {process.env. MOONPAY_API_KEY }
environment = "production"
onError = { handleError }
onRetry = { handleRetry }
/>
)}
</ View >
);
}
Security Considerations
API Key Security : Never expose production API keys in client-side code. Consider using a backend proxy for additional security.
User Verification : MoonPay handles KYC/AML compliance, but ensure your app provides clear information about verification requirements.
API Reference
For detailed API documentation, see:
The MoonPay module provides a seamless bridge between traditional finance and crypto, enabling users to easily onboard into the Solana ecosystem with familiar payment methods.