### Run Plutus Example Application Source: https://github.com/byarcadia-app/plutus/blob/main/docs/payment-setup.md Commands to start the Expo development server and launch the application on an iOS simulator for local testing. ```bash pnpm example:start pnpm example:ios ``` -------------------------------- ### Quick Start: Wrap App with PlutusProvider Source: https://github.com/byarcadia-app/plutus/blob/main/docs/installation.md Demonstrates how to integrate the PlutusProvider component into your React Native application's root. This setup requires your RevenueCat API key and optionally defines entitlement names and callback functions for handling purchase events and errors. ```tsx import { PlutusProvider } from "@byarcadia-app/plutus"; export default function App() { return ( console.error(error.code, error.message), onCustomerInfoUpdated: (info, { isPro }) => { if (isPro) saveProStatus(true); }, onTrackEvent: (name, params) => analytics.track(name, params), }} > ); } ``` -------------------------------- ### Initialize PlutusProvider Source: https://github.com/byarcadia-app/plutus/blob/main/skills/plutus-setup/references/provider-api.md Examples of minimal and full configuration for the PlutusProvider component to initialize RevenueCat services. ```tsx ``` ```tsx console.warn("[Plutus]", error.code, error.cause), onCustomerInfoUpdated: (info, { isPro, isInTrial }) => { analytics.setUserProperty("is_pro", isPro); }, onTrackEvent: (name, params) => analytics.track(name, params), }} translations={{ purchaseError: { title: "Oops!", message: "Something went wrong." }, }} > ``` -------------------------------- ### Install @byarcadia-app/plutus and react-native-purchases Source: https://github.com/byarcadia-app/plutus/blob/main/docs/installation.md Installs the @byarcadia-app/plutus library and its required peer dependency, react-native-purchases (version 9 or higher), using pnpm. Ensure you have pnpm installed and configured for your project. ```bash pnpm add @byarcadia-app/plutus pnpm add react-native-purchases # v9+ required ``` -------------------------------- ### Verify Project Integration Source: https://github.com/byarcadia-app/plutus/blob/main/skills/plutus-setup/SKILL.md Commands to validate the project setup and ensure TypeScript configurations are correct. ```bash npx tsc --noEmit pnpm check ``` -------------------------------- ### Provider Documentation Template for PlutusProvider Source: https://github.com/byarcadia-app/plutus/blob/main/docs/_template.md This template is designed for documenting the PlutusProvider. It covers the main component description, import statement, usage example, and API reference for its props. ```markdown # PlutusProvider {One-line description.} ## Import ```tsx import { PlutusProvider } from "@byarcadia-app/plutus"; ``` ## Usage ```tsx {Code example} ``` ## API Reference | Prop | Type | Default | Description | | ---- | ---- | ------- | ----------- | | ... | ... | ... | ... | ``` -------------------------------- ### Hook Documentation Template for Plutus Source: https://github.com/byarcadia-app/plutus/blob/main/docs/_template.md This template is used for documenting hooks such as usePlutus, useOfferings, usePaywall, and useRescuePaywall. It includes sections for import statements, options, return values, and usage examples. ```markdown ### {hookName} {One-line description.} #### Import ```tsx import { {hookName} } from "@byarcadia-app/plutus"; ``` #### Options | Option | Type | Default | Description | | ------ | ---- | ------- | ----------- | | ... | ... | ... | ... | #### Returns | Property | Type | Description | | -------- | ---- | ----------- | | ... | ... | ... | #### Usage ```tsx {Code example} ``` ``` -------------------------------- ### Install Plutus Dependencies Source: https://github.com/byarcadia-app/plutus/blob/main/skills/plutus-setup/SKILL.md Install the required Plutus package and its peer dependency, react-native-purchases, using the project's detected package manager. ```bash # pnpm (preferred) pnpm add @byarcadia-app/plutus react-native-purchases # yarn yarn add @byarcadia-app/plutus react-native-purchases # npm npm install @byarcadia-app/plutus react-native-purchases ``` -------------------------------- ### Handle Errors in PlutusProvider Source: https://github.com/byarcadia-app/plutus/blob/main/docs/errors.md Shows how to handle errors by implementing the `onError` callback within the `PlutusProvider`. This example demonstrates a switch statement to differentiate between various error codes and execute specific error-handling logic. ```tsx { switch (error.code) { case "INIT_FAILED": crashlytics.recordError(error.cause); break; case "PURCHASE_FAILED": Alert.alert(translations.purchaseError.title, translations.purchaseError.message); break; case "RESTORE_FAILED": Alert.alert(translations.restoreError.title, translations.restoreError.message); break; } }, }} > ``` -------------------------------- ### Access Translations via usePlutus Hook - JavaScript Source: https://github.com/byarcadia-app/plutus/blob/main/docs/translations.md Shows how to access the current translations object within components using the `usePlutus()` hook. The example illustrates accessing and displaying the purchase error title and message. ```javascript const { translations } = usePlutus(); Alert.alert(translations.purchaseError.title, translations.purchaseError.message); ``` -------------------------------- ### Initialize PlutusProvider in React Source: https://github.com/byarcadia-app/plutus/blob/main/docs/provider.md Demonstrates how to import and wrap an application with the PlutusProvider. It requires a RevenueCat API key and entitlement name, while accepting optional callbacks for analytics and error handling. ```tsx import { PlutusProvider } from "@byarcadia-app/plutus"; console.error(error.code, error.message), onCustomerInfoUpdated: (info, { isPro, isInTrial }) => { analytics.setUserProperty("is_pro", isPro); }, onTrackEvent: (name, params) => analytics.track(name, params), }} translations={{ purchaseError: { title: "Oops!", message: "Something went wrong." }, }} > ``` -------------------------------- ### Initialize PlutusProvider Source: https://context7.com/byarcadia-app/plutus/llms.txt The root provider component initializes the RevenueCat SDK and configures global callbacks for error handling, customer info updates, and event tracking. It must wrap the application to provide subscription context to all child components. ```tsx import { PlutusProvider } from "@byarcadia-app/plutus"; import { LOG_LEVEL } from "react-native-purchases"; export default function App() { return ( { console.error("[Plutus]", error.code, error.message); if (error.code === "INIT_FAILED") { crashlytics.recordError(error.cause); } }, onCustomerInfoUpdated: (info, { isPro, isInTrial }) => { analytics.setUserProperty("is_pro", isPro); analytics.setUserProperty("is_trial", isInTrial); }, onTrackEvent: (name, params) => { analytics.track(name, params); }, }} translations={{ purchaseError: { title: "Oops!", message: "We couldn't complete your purchase. Please try again.", }, }} > ); } ``` -------------------------------- ### Configure PlutusProvider with RevenueCat API Key Source: https://github.com/byarcadia-app/plutus/blob/main/docs/payment-setup.md This snippet shows how to wrap your application with PlutusProvider, providing the RevenueCat public API key and entitlement name. It also includes optional callbacks for error handling and event tracking. The API key should be stored securely as an environment variable. ```tsx import { PlutusProvider } from "@byarcadia-app/plutus"; export default function App() { return ( console.warn("[Plutus Error]", error.code, error.cause), onTrackEvent: (name, params) => console.log("[Plutus Event]", name, params), }} > {/* your app */} ); } ``` -------------------------------- ### Load RevenueCat Offerings with useOfferings Hook (React Native) Source: https://context7.com/byarcadia-app/plutus/llms.txt The useOfferings hook fetches RevenueCat offerings and computes trial availability and discount percentages for monthly and annual plans. It's useful for displaying pricing information and trial status in your app. It requires @byarcadia-app/plutus and react-native components. ```tsx import { useOfferings } from "@byarcadia-app/plutus"; import { ActivityIndicator, Text, View } from "react-native"; function PricingDisplay() { const { isLoading, monthlyOffer, annualOffer, rescueOffer, monthlyHasTrial, annualHasTrial, annualDiscountPercentage, rescueOffsetDiscountPercentage, } = useOfferings(); // Pass a refetchKey to trigger re-fetch // const { ... } = useOfferings({ refetchKey: "force-refresh" }); if (isLoading) { return ; } return ( {monthlyOffer && ( Monthly: {monthlyOffer.product.priceString}/month {monthlyHasTrial && Free trial included!} )} {annualOffer && ( Annual: {annualOffer.product.priceString}/year {annualHasTrial && Free trial included!} {annualDiscountPercentage && ( Save {annualDiscountPercentage}% vs monthly! )} )} {rescueOffer && ( Special Offer: {rescueOffer.product.priceString}/year {rescueOffsetDiscountPercentage && ( Save {rescueOffsetDiscountPercentage}% off regular annual! )} )} ); } ``` -------------------------------- ### Load subscription offerings with useOfferings Source: https://github.com/byarcadia-app/plutus/blob/main/docs/hooks.md The useOfferings hook fetches and computes RevenueCat offerings, providing details on monthly and annual packages. It includes helper properties for trial detection and discount percentage calculations. ```tsx import { useOfferings } from "@byarcadia-app/plutus"; const { isLoading, monthlyOffer, annualOffer, rescueOffer, monthlyHasTrial, annualHasTrial, annualDiscountPercentage, rescueOffsetDiscountPercentage, } = useOfferings(); ``` -------------------------------- ### Configure Environment Variables Source: https://github.com/byarcadia-app/plutus/blob/main/skills/plutus-setup/SKILL.md Defines the required RevenueCat API key configuration for local development and production environments using .env files and EAS secrets. ```env EXPO_PUBLIC_REVENUECAT_KEY=your_revenuecat_api_key_here ``` ```bash eas secret:create --scope project --name EXPO_PUBLIC_REVENUECAT_KEY --value ``` -------------------------------- ### PlutusProvider Component Source: https://github.com/byarcadia-app/plutus/blob/main/docs/provider.md The root provider component that initializes the RevenueCat SDK and manages global entitlement state. ```APIDOC ## PlutusProvider ### Description Initializes the RevenueCat SDK, manages entitlement state, and distributes configuration to all hooks within the application tree. ### Props - **apiKey** (string) - Required - RevenueCat API key. Empty values trigger `onError`. - **entitlementName** (string) - Required - Entitlement identifier to check for pro/trial status. - **logLevel** (LOG_LEVEL) - Optional - RevenueCat SDK log level. Defaults to `LOG_LEVEL.ERROR`. - **offerings** (object) - Optional - Offering identifiers for default and rescue paywalls. - **callbacks** (PlutusCallbacks) - Optional - Event callbacks for SDK lifecycle events. - **translations** (Partial) - Optional - Override default UI translation strings. ### Callbacks - **onError** (function) - Called on SDK errors (init, purchase, offerings, restore). - **onCustomerInfoUpdated** (function) - Called when RevenueCat customer info changes. - **onTrackEvent** (function) - Analytics event callback used as a global fallback. ### Usage Example ```tsx console.error(error.message), onTrackEvent: (name, params) => analytics.track(name, params) }} > ``` ``` -------------------------------- ### Implement useRescuePaywall hook Source: https://github.com/byarcadia-app/plutus/blob/main/docs/hooks.md Demonstrates how to initialize the useRescuePaywall hook to manage a single rescue package purchase flow. It handles purchase success, restoration, and navigation to legal URLs. ```tsx import { useRescuePaywall } from "@byarcadia-app/plutus"; const { isPurchasing, handlePurchasePackage, handleRestorePurchases, handleClosePress, handleTermsPress, handlePrivacyPress, } = useRescuePaywall({ rescueOffer, onPurchaseSuccess: () => router.back(), termsUrl: "https://example.com/terms", privacyUrl: "https://example.com/privacy", }); ``` -------------------------------- ### Development Lifecycle Commands Source: https://github.com/byarcadia-app/plutus/blob/main/CONTRIBUTING.md Standard shell commands for managing dependencies, verifying code quality, and building the project using pnpm. ```shell pnpm install pnpm check pnpm lint pnpm fmt:check pnpm fmt pnpm build pnpm dev ``` -------------------------------- ### Implement Rescue Paywall with useRescuePaywall Source: https://context7.com/byarcadia-app/plutus/llms.txt The useRescuePaywall hook manages the purchase flow for single rescue or discount offers. It handles purchase actions, restoration, and event tracking, typically used when a user declines the primary subscription offer. ```tsx import { useOfferings, useRescuePaywall, usePlutus } from "@byarcadia-app/plutus"; import { useRouter } from "expo-router"; import { ActivityIndicator, Pressable, Text, View } from "react-native"; function RescueOfferScreen() { const { isPro } = usePlutus(); const router = useRouter(); const { rescueOffer, rescueOffsetDiscountPercentage, isLoading } = useOfferings(); const { isPurchasing, handlePurchasePackage, handleRestorePurchases, handleClosePress, handleTermsPress, handlePrivacyPress, } = useRescuePaywall({ rescueOffer, onClose: () => router.back(), onPurchaseSuccess: () => { console.log("Rescue offer purchased!"); router.back(); }, onPurchaseFailed: () => { console.warn("Rescue purchase failed"); }, onRestoreSuccess: () => { router.back(); }, onRestoreFailed: () => { console.warn("Restore failed"); }, onTrackEvent: (name, params) => { analytics.track(name, params); }, termsUrl: "https://example.com/terms", privacyUrl: "https://example.com/privacy", }); if (isPro || isLoading || !rescueOffer) { return null; } return ( Wait! Here's a special offer just for you {rescueOffer.product.priceString}/year {rescueOffsetDiscountPercentage && ( Save {rescueOffsetDiscountPercentage}% off regular price! )} {isPurchasing ? : Claim Offer} Restore Purchases No Thanks ); } ``` -------------------------------- ### Configure EAS Project Secret Source: https://github.com/byarcadia-app/plutus/blob/main/docs/payment-setup.md Command to set the RevenueCat API key as an EAS project secret, ensuring it is available across all build profiles. ```bash eas secret:create --scope project --name EXPO_PUBLIC_REVENUECAT_KEY --value your_key_here ``` -------------------------------- ### PlutusProvider Component Source: https://github.com/byarcadia-app/plutus/blob/main/skills/plutus-setup/references/provider-api.md The PlutusProvider component is the root component for the Plutus SDK. It initializes RevenueCat and provides subscription state to all child hooks. It accepts several props for configuration, including API keys, entitlement names, log levels, offering identifiers, callbacks, and translations. ```APIDOC ## PlutusProvider Component ### Description The `PlutusProvider` component initializes the RevenueCat SDK and distributes state to all Plutus hooks. It requires an `apiKey` and `entitlementName` to function correctly. Optional props allow for customization of log levels, offerings, callbacks, and translations. ### Props #### Required Props - **apiKey** (string) - Required - RevenueCat API key. If empty or whitespace, SDK initialization is skipped, and `onError` is called with `INIT_FAILED`. - **entitlementName** (string) - Required - Entitlement identifier. Must exactly match the RevenueCat dashboard and is case-sensitive. #### Optional Props - **logLevel** (LOG_LEVEL) - Optional - RevenueCat SDK log level. Defaults to `LOG_LEVEL.ERROR`. Use `LOG_LEVEL.DEBUG` for development. - **offerings** ({ default?: string; rescue?: string }) - Optional - Offering identifiers for default and rescue paywalls. Defaults to `{ default: "default", rescue: "rescue" }`. - **callbacks** (PlutusCallbacks) - Optional - Event callbacks for various SDK events. - **translations** (Partial) - Optional - Override default translation strings. Defaults to English. ### Callbacks (within `callbacks` prop) - **onError** ((error: PlutusError) => void) - Called when SDK errors occur (init, purchase, offerings, restore). - **onCustomerInfoUpdated** ((info: CustomerInfo, state: { isPro: boolean; isInTrial: boolean }) => void) - Called when RevenueCat customer information changes. - **onTrackEvent** ((name: string, params?: Record) => void) - Analytics event callback, used as a fallback by all hooks. ### PlutusError Shape ```typescript interface PlutusError { code: PlutusErrorCode; message: string; cause?: Error; } type PlutusErrorCode = "INIT_FAILED" | "OFFERINGS_FAILED" | "PURCHASE_FAILED" | "RESTORE_FAILED"; ``` ### Request Example (Minimal Setup) ```tsx ``` ### Request Example (Full Setup) ```tsx console.warn("[Plutus]", error.code, error.cause), onCustomerInfoUpdated: (info, { isPro, isInTrial }) => { analytics.setUserProperty("is_pro", isPro); }, onTrackEvent: (name, params) => analytics.track(name, params), }} translations={{ purchaseError: { title: "Oops!", message: "Something went wrong." }, }} > ``` ``` -------------------------------- ### Version Management with Changesets Source: https://github.com/byarcadia-app/plutus/blob/main/CONTRIBUTING.md Command to initialize a new changeset for versioning and changelog generation when making public API changes or bug fixes. ```shell pnpm changeset ``` -------------------------------- ### Project File Structure Source: https://github.com/byarcadia-app/plutus/blob/main/CONTRIBUTING.md The standard directory layout for the source code, emphasizing the separation of hooks, providers, and type definitions. ```text src/ ├── index.ts ├── types.ts ├── translations.ts ├── provider/ │ ├── plutus-provider.tsx │ └── use-plutus.ts └── hooks/ ├── use-offerings.ts ├── use-paywall.ts └── use-rescue-paywall.ts ``` -------------------------------- ### Available Hooks Source: https://github.com/byarcadia-app/plutus/blob/main/skills/plutus-setup/references/provider-api.md These hooks can be used within a component wrapped by `PlutusProvider` to access subscription state and functionality. ```APIDOC ## Available Hooks ### Description These hooks provide access to various aspects of the Plutus SDK's functionality. They require an ancestor `PlutusProvider` component to be present in the component tree. ### Hooks - **usePlutus()** - **Purpose**: Provides core state including `isPro`, `isInTrial`, `isReady`, and the `purchasePackage` function. - **useOfferings()** - **Purpose**: Loads offerings with trial detection and discount calculation capabilities. - **usePaywall()** - **Purpose**: Orchestrates the purchase flow for the main paywall. - **useRescuePaywall()** - **Purpose**: Manages the purchase flow specifically for rescue or discount offers. ``` -------------------------------- ### Access subscription state with usePlutus Source: https://context7.com/byarcadia-app/plutus/llms.txt The usePlutus hook provides access to the user's entitlement status, trial state, and utility methods like purchase and restore. It is used to build UI components that react to the user's current subscription level. ```tsx import { usePlutus } from "@byarcadia-app/plutus"; import { Alert, Button, Linking, Text, View } from "react-native"; function SubscriptionStatus() { const { isPro, isInTrial, isReady, managementURL, purchasePackage, restorePurchases, translations, } = usePlutus(); if (!isReady) { return Loading...; } const handleRestore = async () => { const restored = await restorePurchases(); if (restored) { Alert.alert("Success", "Your purchases have been restored!"); } else { Alert.alert(translations.restoreError.title, translations.restoreError.message); } }; const handleManageSubscription = () => { if (managementURL) { Linking.openURL(managementURL); } }; return ( Status: {isPro ? "Pro" : "Free"} {isInTrial && Currently in trial period} {isPro && managementURL && (