=============== LIBRARY RULES =============== From library maintainers: - Install through npm aliases so every import stays unchanged: "react-native-purchases": "npm:@revenuedot/react-native-purchases@" and the same for react-native-purchases-ui. - Keep `import Purchases from "react-native-purchases"`. Then run `npx pod-install` (bare React Native) or `npx expo prebuild` (Expo). - RevenueDot Cloud (https://api.revenuedot.app) is the default API host. For a self-hosted server, call `await Purchases.setProxyURL("https://revenuedot.example.com")` before `Purchases.configure`. - Pass each app's public key from the RevenueDot dashboard to `Purchases.configure`: appl_ for iOS and goog_ for Android. ### Build and run MagicWeather example Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/DEVELOPMENT.md Run these commands from the MagicWeather directory to install dependencies, install pods, and launch the app on iOS or Android. ```bash yarn ``` ```bash yarn pods ``` ```bash yarn ios ``` ```bash yarn android ``` -------------------------------- ### Bootstrap the development environment Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/DEVELOPMENT.md Run this command from the repository root to link the local package so changes are automatically applied to the purchaseTesterTypescript example. ```bash yarn bootstrap ``` -------------------------------- ### Run purchaseTesterTypescript on a device or simulator Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/DEVELOPMENT.md Use these commands from the repository root to run the example app. If a device is connected it will run there, otherwise it will use a simulator. ```bash yarn example android ``` ```bash yarn example ios ``` -------------------------------- ### Common Development Commands Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/AGENTS.md Common development commands for the react-native-purchases project. Run yarn bootstrap to install dependencies and bootstrap the workspace. Use yarn build and yarn build-watch for TypeScript compilation, yarn test for tests, yarn typecheck for type checking, and yarn tslint for linting (despite the name, it runs the project's configured linter). Launch the example app with yarn example ios or yarn example android, and prepare for Expo testing with yarn prepare-expo. ```bash yarn bootstrap ``` ```bash yarn build ``` ```bash yarn build-watch ``` ```bash yarn test ``` ```bash yarn typecheck ``` ```bash yarn tslint ``` ```bash yarn example ios ``` ```bash yarn example android ``` ```bash yarn prepare-expo ``` -------------------------------- ### Install react-native-purchases with npx expo install Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/README.md Install the react-native-purchases SDK in an Expo project. Requires a development build for full native functionality; in Expo Go, the SDK runs in Preview API Mode with JavaScript mocks. ```bash $ npx expo install react-native-purchases ``` -------------------------------- ### Configure SDK with object parameters Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/v4_to_v5_migration_guide.md Configures the SDK with an object containing all parameters. Replaces the removed setUp method and the previous configure signature. ```javascript Purchases.configure({ apiKey: "key", appUserID: "user ID", observerMode: false, userDefaultsSuiteName: "suite name", useAmazon: true }); ``` -------------------------------- ### Enable local build for Android common files Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/DEVELOPMENT.md Run this command from the Android example directory to link the local purchases-hybrid-common project. Replace the path with the correct location on your machine. ```bash gradle enableLocalBuild -PcommonPath="$HOME/Development/repos/purchases-hybrid-common/android" ``` -------------------------------- ### Install RevenueDot React Native SDK via npm aliases Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/README.md Use this package.json snippet to install the RevenueDot React Native SDK via npm aliases, keeping existing imports from 'react-native-purchases' unchanged. After adding these dependencies, run 'npx pod-install' for bare React Native or 'npx expo prebuild' for Expo. The native side resolves to RevenueDot's RevenueDotPurchasesHybridCommon pod and app.revenuedot.purchases:purchases-hybrid-common. ```json { "dependencies": { "react-native-purchases": "npm:@revenuedot/react-native-purchases@10.10.2", "react-native-purchases-ui": "npm:@revenuedot/react-native-purchases-ui@10.10.2" } } ``` -------------------------------- ### Yarn workspaces configuration Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/AGENTS.md Yarn workspaces configuration listing the packages included in the monorepo. This is used for managing dependencies across the example app and the UI package. ```yaml workspaces: - examples/purchaseTesterTypescript - react-native-purchases-ui ``` -------------------------------- ### Enable local native SDK build Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/AGENTS.md Run this command from the project root to enable a local build of purchases-hybrid-common for testing native SDK changes. Replace the path with the actual location of the purchases-hybrid-common repository. ```bash cd android && ./gradlew enableLocalBuild -PpurchasesPath="path/to/purchases-hybrid-common" ``` -------------------------------- ### RevenueCatUI.presentPaywall() Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/react-native-purchases-ui/README.md Presents the current offering's paywall modally. Optionally accepts an offering object to display a specific offering. Returns a PAYWALL_RESULT indicating the outcome. ```APIDOC ## RevenueCatUI.presentPaywall() ### Description Presents the current offering's paywall modally. Optionally accepts an offering object to display a specific offering. Returns a PAYWALL_RESULT indicating the outcome. ### Method presentPaywall ### Signature `RevenueCatUI.presentPaywall(options?: { offering?: Offering }): Promise` ### Parameters #### Options (optional) - **offering** (Offering) - Optional - The offering to display. If not provided, the current offering is used. ### Return Value - **Promise** - Resolves to a PAYWALL_RESULT enum value: NOT_PRESENTED, ERROR, CANCELLED, PURCHASED, or RESTORED. ### Example ```tsx import RevenueCatUI, { PAYWALL_RESULT } from "react-native-purchases-ui"; async function presentPaywall(): Promise { const paywallResult: PAYWALL_RESULT = await RevenueCatUI.presentPaywall(); switch (paywallResult) { case PAYWALL_RESULT.NOT_PRESENTED: case PAYWALL_RESULT.ERROR: case PAYWALL_RESULT.CANCELLED: return false; case PAYWALL_RESULT.PURCHASED: case PAYWALL_RESULT.RESTORED: return true; default: return false; } } ``` With a specific offering: ```tsx await RevenueCatUI.presentPaywall({ offering }); ``` ``` -------------------------------- ### Display specific offering with Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/react-native-purchases-ui/README.md Renders the paywall for a specific offering using the options prop. The onRestoreCompleted listener is called when a restore completes, even if no entitlements are granted. ```tsx import React from 'react'; import { View } from 'react-native'; import RevenueCatUI from 'react-native-purchases-ui'; return ( { // Optional listener. Called when a restore has been completed. // This may be called even if no entitlements have been granted. }} onDismiss={() => { // Dismiss the paywall, i.e. remove the view, navigate to another screen, etc. // Will be called when the close button is pressed (if enabled) or when a purchase succeeds. }} /> ); ``` -------------------------------- ### Present paywall with RevenueCatUI.presentPaywall() Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/react-native-purchases-ui/README.md Presents the current offering's paywall modally and returns a boolean indicating whether the user purchased or restored. The PAYWALL_RESULT enum values are used to determine the outcome. ```tsx import RevenueCatUI, { PAYWALL_RESULT } from "react-native-purchases-ui"; async function presentPaywall(): Promise { const paywallResult: PAYWALL_RESULT = await RevenueCatUI.presentPaywall(); switch (paywallResult) { case PAYWALL_RESULT.NOT_PRESENTED: case PAYWALL_RESULT.ERROR: case PAYWALL_RESULT.CANCELLED: return false; case PAYWALL_RESULT.PURCHASED: case PAYWALL_RESULT.RESTORED: return true; default: return false; } } ``` -------------------------------- ### Configure PurchasesAreCompletedBy with StoreKit 1 Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/migrations/v8-MIGRATION.md Configures the SDK to use StoreKit 1 when purchases are completed by your app using StoreKit 1. This is required to observe purchases correctly. ```typescript Purchases.configure({ apiKey, appUserID, { type: PURCHASES_ARE_COMPLETED_BY_TYPE.MY_APP, storeKitVersion: STOREKIT_VERSION.STOREKIT_1, }, }); ``` -------------------------------- ### Filter subscription options on StoreProduct Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/migrations/v6-MIGRATION.md Shows how to access and filter subscription options from a StoreProduct to find base plans, default options, free offers, and trial offers. Useful when more control over offers is needed. ```dart const basePlan = storeProduct.subscriptionOptions?.filter((option) => { option.isBasePlan }); const defaultOption = storeProduct.defaultOption const freeOffer = storeProduct.subscriptionOptions?.filter((option) => { !!option.freePhase }); const trialOffer = storeProduct.subscriptionOptions?.filter((option) => { !!option.introPhase }); ``` -------------------------------- ### Configure SDK with storeKitVersion Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/migrations/v8-MIGRATION.md Configures the SDK with a specific StoreKit version. The `storeKitVersion` parameter replaces `usesStoreKit2IfAvailable` and defaults to letting the iOS SDK determine the most appropriate version at runtime. ```typescript Purchases.configure({ apiKey, STOREKIT_VERSION.STOREKIT_1, }); ``` -------------------------------- ### Configure Amazon Store support Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/v4_to_v5_migration_guide.md Enables Amazon Store support by passing the Amazon API key and setting useAmazon to true. Required for using the Amazon Store with the SDK. ```javascript Purchases.configure({ apiKey: "AMAZON_API_KEY", useAmazon: true }); ``` -------------------------------- ### Configure RevenueDot react-native-purchases with setProxyURL and configure Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/README.md Configure the RevenueDot fork of react-native-purchases. The setProxyURL call is only needed for self-hosted servers; RevenueDot Cloud is the default. The apiKey is the app's public key from the RevenueDot dashboard, selected by platform. ```ts import { Platform } from "react-native"; import Purchases from "react-native-purchases"; // Self-hosted server only: RevenueDot Cloud (https://api.revenuedot.app) is the default. await Purchases.setProxyURL("https://revenuedot.example.com"); Purchases.configure({ apiKey: Platform.OS === "ios" ? "appl_..." : "goog_..." }); // each app's public key from the RevenueDot dashboard ``` -------------------------------- ### Display current offering with Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/react-native-purchases-ui/README.md Renders the paywall component for the current offering with manual control over when and how it appears. The onDismiss callback is called when the close button is pressed (if enabled) or when a purchase succeeds. ```tsx import React from 'react'; import { View } from 'react-native'; import RevenueCatUI from 'react-native-purchases-ui'; return ( { // Dismiss the paywall, i.e. remove the view, navigate to another screen, etc. // Will be called when the close button is pressed (if enabled) or when a purchase succeeds. }} /> ); ``` -------------------------------- ### Record purchase on macOS with StoreKit 2 Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/migrations/v8-MIGRATION.md Immediately records a purchase on macOS when purchases are completed by your app using StoreKit 2. By default, the SDK does not detect the purchase until the user foregrounds the app. ```typescript await Purchases.recordPurchase(productID); ``` -------------------------------- ### Present paywall with specific offering Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/react-native-purchases-ui/README.md Optionally pass an offering object to display a specific offering in the paywall. ```tsx await RevenueCatUI.presentPaywall({ offering }); ``` -------------------------------- ### Update PurchasesHybridCommon version Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/DEVELOPMENT.md Use this fastlane command to update the PurchasesHybridCommon version to the specified new version. ```bash fastlane update_hybrid_common version:{new version} ``` -------------------------------- ### RevenueCatUI.presentPaywallIfNeeded() Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/react-native-purchases-ui/README.md Displays the paywall only if the required entitlement is not unlocked, useful for gating access. Optionally accepts a specific offering. ```APIDOC ## RevenueCatUI.presentPaywallIfNeeded() ### Description Displays the paywall only if the required entitlement is not unlocked, useful for gating access. Optionally accepts a specific offering. ### Method presentPaywallIfNeeded ### Signature `RevenueCatUI.presentPaywallIfNeeded(options: { requiredEntitlementIdentifier: string; offering?: Offering }): Promise` ### Parameters #### Options (required) - **requiredEntitlementIdentifier** (string) - Required - The entitlement identifier that must be unlocked to skip the paywall. - **offering** (Offering) - Optional - The offering to display. If not provided, the current offering is used. ### Return Value - **Promise** - Resolves to a PAYWALL_RESULT enum value. ### Example ```tsx const result = await RevenueCatUI.presentPaywallIfNeeded({ requiredEntitlementIdentifier: "pro" }); ``` With a specific offering: ```tsx await RevenueCatUI.presentPaywallIfNeeded({ offering, requiredEntitlementIdentifier: "pro" }); ``` ``` -------------------------------- ### Component Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/react-native-purchases-ui/README.md A React component that provides manual control over when and how the paywall is rendered in your component tree. Supports lifecycle listeners for purchase and restore events. ```APIDOC ## Component ### Description A React component that provides manual control over when and how the paywall is rendered in your component tree. Supports lifecycle listeners for purchase and restore events. ### Props - **options** (object) - Optional - Configuration options. - **offering** (Offering) - Optional - The offering to display. If not provided, the current offering is used. - **onPurchaseStarted** (callback) - Optional - Called when a purchase is started. - **onPurchaseCompleted** (callback) - Optional - Called when a purchase is completed. - **onPurchaseError** (callback) - Optional - Called when a purchase error occurs. - **onPurchaseCancelled** (callback) - Optional - Called when a purchase is cancelled. - **onRestoreStarted** (callback) - Optional - Called when a restore is started. - **onRestoreCompleted** (callback) - Optional - Called when a restore has been completed. Receives an object with `customerInfo` of type `CustomerInfo`. - **onRestoreError** (callback) - Optional - Called when a restore error occurs. - **onDismiss** (callback) - Optional - Called when the close button is pressed (if enabled) or when a purchase succeeds. Use to dismiss the paywall. ### Example: Displaying the Current Offering ```tsx import React from 'react'; import { View } from 'react-native'; import RevenueCatUI from 'react-native-purchases-ui'; return ( { // Dismiss the paywall, i.e. remove the view, navigate to another screen, etc. // Will be called when the close button is pressed (if enabled) or when a purchase succeeds. }} /> ); ``` ### Example: Displaying a Specific Offering ```tsx import React from 'react'; import { View } from 'react-native'; import RevenueCatUI from 'react-native-purchases-ui'; return ( { // Optional listener. Called when a restore has been completed. // This may be called even if no entitlements have been granted. }} onDismiss={() => { // Dismiss the paywall, i.e. remove the view, navigate to another screen, etc. // Will be called when the close button is pressed (if enabled) or when a purchase succeeds. }} /> ); ``` ``` -------------------------------- ### Configure Purchases for Galaxy Store Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/react-native-purchases-store-galaxy/README.md Configures the Purchases SDK for the Galaxy Store using the GALAXY_BILLING_MODE.TEST billing mode. Requires the react-native-purchases-store-galaxy package and a valid Galaxy Store API key. ```ts import Purchases from "react-native-purchases"; import { GALAXY_BILLING_MODE } from "react-native-purchases-store-galaxy"; Purchases.configure({ apiKey: "galx_XYZ", store: "GALAXY", galaxyBillingMode: GALAXY_BILLING_MODE.TEST, }); ``` -------------------------------- ### Configure PurchasesAreCompletedBy with StoreKit 2 Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/migrations/v8-MIGRATION.md Enables PurchasesAreCompletedBy with MY_APP type and StoreKit 2. When specifying that your app completes purchases, you must provide the StoreKit version your app uses on iOS; on Android any value is accepted. ```typescript Purchases.configure({ apiKey, appUserID, { type: PURCHASES_ARE_COMPLETED_BY_TYPE.MY_APP, storeKitVersion: STOREKIT_VERSION.STOREKIT_2, }, }); ``` -------------------------------- ### Present paywall if needed with specific offering Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/react-native-purchases-ui/README.md Displays the paywall for a specific offering only if the required entitlement is not unlocked. ```tsx await RevenueCatUI.presentPaywallIfNeeded({ offering, requiredEntitlementIdentifier: "pro" }); ``` -------------------------------- ### Delete Gradle caches Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/TROUBLESHOOTING.md Deletes the Gradle cache directory to resolve Android Studio not updating packages. ```bash rm -rf $HOME/.gradle/caches/ ``` -------------------------------- ### Present paywall if needed with required entitlement Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/react-native-purchases-ui/README.md Displays the paywall only if the required entitlement is not unlocked, useful for gating access. The requiredEntitlementIdentifier is set to "pro". ```tsx const result = await RevenueCatUI.presentPaywallIfNeeded({ requiredEntitlementIdentifier: "pro" }); ``` -------------------------------- ### Compile TypeScript changes manually Source: https://github.com/revenuedot/react-native-purchases/blob/revenuedot/main-patches/DEVELOPMENT.md If watchman does not automatically detect changes to .ts files, run this command to compile them. ```bash npm run build ```