This example showcases how to build a Movement blockchain wallet using Privy's Expo SDK in a React Native application.
git clone https://github.com/dumbdevss/Movement-react-native-privy-template.git movement-privy-wallet
cd movement-privy-walletnpm installNavigate to the expo-backend directory and start the backend server that connects to the Aptos SDK:
cd expo-backend
npm install
npm startKeep this backend server running - it's required for Movement wallet functionality.
Before configuring your app, you need to set up your Privy Dashboard:
- Go to your Privy Dashboard
- Configure an app client for mobile
- Add your App ID and Client ID (you'll use these in the next step)
- Set App Identifiers to include:
host.exp.Exponent(for Expo Go development)dev.privy.example(or replace with your own identifier)
- Set URL Schemes to include:
exp(required for Expo)myapp(or replace with your custom scheme)
Update the app.json file with your Privy credentials and custom settings:
{
"expo": {
"extra": {
"privyAppId": "<APP_ID>",
"privyClientId": "<CLIENT_ID>",
"passkeyAssociatedDomain": "https://<your-associated-domain>"
},
"scheme": "myapp",
"ios": {
"usesAppleSignIn": true,
"supportsTablet": true,
"bundleIdentifier": "dev.privy.example",
"associatedDomains": ["webcredentials:<your-associated-domain>"],
"infoPlist": {
"NSAppTransportSecurity": {
"NSAllowsArbitraryLoads": true
}
}
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/images/adaptive-icon.png",
"backgroundColor": "#ffffff"
},
"package": "dev.privy.example"
},
}
}Customization Options:
- Replace
myappwith your own URL scheme (and add it to Dashboard URL schemes) - Replace
dev.privy.examplewith your own bundle identifier (and add it to Dashboard App identifiers) - Configure
passkeyAssociatedDomainfor iOS passkey support
Open a new terminal window (keep the backend running) and start the Expo development server:
npm startThis will start the Expo development server. You can then:
- Press
ifor iOS simulator - Press
afor Android emulator - Scan QR code with Expo Go app on your device
Login or sign up using Privy's pre-built modals optimized for mobile.
import { usePrivy } from "@privy-io/expo";
const { user } = usePrivy();
// User is automatically shown LoginScreen if not authenticatedProgrammatically create an embedded wallet for the Movement blockchain using the Aptos chain type.
import { useCreateWallet } from "@privy-io/expo/extended-chains";
const { createWallet } = useCreateWallet();
// Create Movement wallet
await createWallet({
chainType: "aptos",
});Send transactions on the Movement blockchain with native mobile UX.
import { useCreateWallet } from "@privy-io/expo/extended-chains";
const { createWallet } = useCreateWallet();
const handleSendTransaction = useCallback(async () => {
if (!activeWallet) return;
setIsLoadingSend(true);
try {
const result = await signAndSubmitTransaction(
activeWallet.public_key,
activeWallet.address,
"0x1::aptos_account::transfer",
[],
[
"0x9b0e90c9f3d8e5b3d8cfc9a0c0f9621c742e5675b4f4e772fbef457b73ef4e4a",
1_00000000
] // Replace with your test address
);
showModal(
"Transaction Sent ✅",
`Hash: ${result.transactionHash}\nStatus: ${result.vmStatus}`
);
// Refresh balance
const newBalance = await getWalletBalance(activeWallet.address);
setWalletBalance(newBalance / 1e8);
} catch (error: any) {
console.error("Transaction error:", error);
showModal(
"Transaction Failed",
error.message || "Failed to send transaction"
);
} finally {
setIsLoadingSend(false);
}
}, [activeWallet, signAndSubmitTransaction, getWalletBalance]);Transaction Details:
- Uses
signAndSubmitTransactionfunction from the backend - Transfers APT tokens using
0x1::aptos_account::transfer - Amount is specified in Octas (1 APT = 100,000,000 Octas)
- Automatically refreshes wallet balance after successful transaction
Before running your app, ensure you have:
- ✅ Started the expo-backend server (connects to Aptos SDK)
- ✅ Added your App ID and Client ID to
app.json - ✅ Set App Identifiers in Dashboard:
host.exp.Exponentanddev.privy.example(or your custom identifier) - ✅ Set URL Schemes in Dashboard:
expandmyapp(or your custom scheme) - ✅ Updated bundle identifiers in
app.jsonif using custom values - ✅ Configured associated domains for iOS passkey support (optional)
This application uses:
- Frontend: Expo React Native with Privy SDK
- Backend: Node.js server (
expo-backend) that interfaces with the Aptos SDK - Blockchain: Movement Network (Aptos-compatible)
The backend server is essential for wallet operations and must be running before using the app.
- Privy Dashboard
- Privy Documentation
- Expo SDK
- Expo Documentation
- Movement Network
- Aptos SDK Documentation
For issues or questions:
- Check the Privy Documentation
- Join the Movement community
- Review Expo documentation for React Native specific questions