Mobile Applications
React Native & Expo Mobile Integration
Localize in-app subscription pricing, paywalls, and coin packs across iOS and Android with automatic country detection and offline caching.
Custom useParity Hook with AsyncStorage Caching
Create a lightweight hook with AsyncStorage persistence to query the ParityEdge Anycast Edge API once per app session:
// hooks/useParity.ts
import { useState, useEffect } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
export interface ParityData {
eligible: boolean;
discountPercentage: number;
countryName: string;
countryCode: string;
currency: string;
couponCode: string;
tier: number;
}
const CACHE_KEY = '@parityedge_cache_v1';
const EDGE_URL = 'https://api.parityedge.app/v1/lookup?pid=prj_live_YOUR_KEY';
export function useParity() {
const [parity, setParity] = useState<ParityData | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function loadParity() {
try {
const cached = await AsyncStorage.getItem(CACHE_KEY);
if (cached) {
setParity(JSON.parse(cached));
setLoading(false);
return;
}
const res = await fetch(EDGE_URL, {
headers: { Accept: 'application/json' },
});
if (res.ok) {
const data = await res.json();
setParity(data);
await AsyncStorage.setItem(CACHE_KEY, JSON.stringify(data));
}
} catch (err) {
console.warn('[ParityEdge] Mobile resolution error:', err);
} finally {
setLoading(false);
}
}
loadParity();
}, []);
const getDiscountedPrice = (basePrice: number) => {
if (parity?.eligible && parity.discountPercentage > 0) {
const multiplier = (100 - parity.discountPercentage) / 100;
return Number((basePrice * multiplier).toFixed(2));
}
return basePrice;
};
return { parity, loading, getDiscountedPrice };
}Mobile Paywall & In-App Purchase UI
// screens/PaywallScreen.tsx
import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Linking } from 'react-native';
import { useParity } from '../hooks/useParity';
export function PaywallScreen() {
const { parity, loading, getDiscountedPrice } = useParity();
const basePrice = 49.00;
const finalPrice = getDiscountedPrice(basePrice);
const handleCheckout = () => {
const coupon = parity?.couponCode;
const url = coupon
? `https://buy.stripe.com/sample_pro?prefilled_promo_code=${coupon}`
: 'https://buy.stripe.com/sample_pro';
Linking.openURL(url);
};
return (
<View style={styles.container}>
<Text style={styles.title}>Unlock Premium Access</Text>
{parity?.eligible && parity.discountPercentage > 0 && (
<View style={styles.banner}>
<Text style={styles.bannerText}>
🎉 Special {parity.discountPercentage}% purchasing power discount for {parity.countryName}!
</Text>
</View>
)}
<Text style={styles.price}>${finalPrice.toFixed(2)} / year</Text>
<TouchableOpacity style={styles.button} onPress={handleCheckout}>
<Text style={styles.buttonText}>Subscribe Now</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 24, justifyContent: 'center', backgroundColor: '#0B0F19' },
title: { fontSize: 24, fontWeight: 'bold', color: '#FFFFFF', textAlign: 'center' },
banner: { backgroundColor: '#064E3B', padding: 12, borderRadius: 12, marginVertical: 16 },
bannerText: { color: '#34D399', fontSize: 13, textAlign: 'center', fontWeight: '600' },
price: { fontSize: 32, fontWeight: '800', color: '#FFFFFF', textAlign: 'center', marginVertical: 12 },
button: { backgroundColor: '#00C57A', padding: 16, borderRadius: 12, alignItems: 'center' },
buttonText: { color: '#000000', fontWeight: 'bold', fontSize: 16 },
});Mobile Best Practices
AsyncStorage Session Cache
Cache the response in AsyncStorage or MMKV to ensure instant paywall rendering with zero network latency on subsequent app launches.
Anti-VPN Security Shield
The ParityEdge edge engine detects and filters datacenter proxies in sub-10ms, preventing proxy abuse on mobile checkout sessions.