Basic Usage

Learn how to identify users, build paywalls, and handle purchases with Voidhash.

Setup

Wrap Your App with the Provider

Wrap your app with the Voidhash Provider to enable hooks throughout your application:

app/_layout.tsx
import { voidhash } from "utils/voidhash/client";

export default function RootLayout() {
  return <voidhash.Provider>{/* Your app content */}</voidhash.Provider>;
}

User Identification

Identifying Users

After a user signs in with your authentication system, identify them with Voidhash using a unique, hard-to-guess identifier:

import { voidhash } from "utils/voidhash/client";

const handleSignIn = async (email: string) => {
  // Your authentication logic
  const user = await yourAuthService.signIn(email);

  // Identify the user with Voidhash
  await voidhash.client.identify(user.id, {
    email: user.email,
    name: user.name,
  });
};

Security

The identifier should be unique and hard to guess (like a UUID). Never use predictable values like sequential IDs or email addresses as the primary identifier.

Signing Out

When a user signs out, make sure to also sign them out from Voidhash:

const handleSignOut = async () => {
  // Your sign-out logic
  await yourAuthService.signOut();

  // Sign out from Voidhash
  await voidhash.client.signOut();
};

Building a Paywall

Fetching Products

Use the useProducts hook to fetch available products defined in your schema:

app/paywall.tsx
import { voidhash } from "utils/voidhash/client";

export default function PaywallScreen() {
  const { data: products, isLoading } = voidhash.useProducts();

  if (isLoading) {
    return <LoadingSpinner />;
  }

  return (
    <View>
      {products.toList().map((product) => (
        <View key={product.slug}>
          <Text>{product.name}</Text>
          <Text>{product.price}</Text>
          <Text>{product.currency}</Text>
        </View>
      ))}
    </View>
  );
}

Making a Purchase

Use the usePurchase hook to handle purchases:

const { purchase, isLoading: isPurchasing } = voidhash.usePurchase();

purchase(product);

The purchase flow is handled automatically by Voidhash, including:

  • Initiating the payment with the app store
  • Verifying the receipt
  • Activating the subscription
  • Updating the customer's perks

Complete Paywall Example

Here's a full paywall implementation with product selection:

app/paywall.tsx
import type { SubscriptionProduct } from "@voidhash/react-native/build/core/entities/product";
import { useState } from "react";
import { Text, TouchableOpacity, View } from "react-native";
import { voidhash } from "utils/voidhash/client";

export default function PaywallScreen() {
  const [selectedProduct, setSelectedProduct] =
    useState<SubscriptionProduct | null>(null);

  const { purchase, isLoading: isPurchasing } = voidhash.usePurchase();
  const { data: products, isLoading: areProductsLoading } =
    voidhash.useProducts();

  if (areProductsLoading) {
    return <LoadingSpinner />;
  }

  const handlePurchase = () => {
    if (!selectedProduct) {
      return;
    }
    purchase(selectedProduct);
  };

  return (
    <View>
      <Text>Choose a plan to continue</Text>

      <View>
        {products.toList().map((product) => (
          <TouchableOpacity
            key={product.slug}
            onPress={() => setSelectedProduct(product)}
          >
            <View>
              <Text>{product.name}</Text>
              <Text>{Math.round(product.price * 100) / 100}</Text>
            </View>
          </TouchableOpacity>
        ))}
      </View>

      <Button
        onPress={handlePurchase}
        disabled={!selectedProduct || isPurchasing}
        title={isPurchasing ? "Purchasing..." : "Continue"}
      />
    </View>
  );
}

Accessing Customer Data

Current Customer Information

Use the useCurrentCustomer hook to access the current customer's subscription and perk information:

app/customer.tsx
import { voidhash } from "utils/voidhash/client";

export default function CustomerScreen() {
  const { data: customer, isLoading, error } = voidhash.useCurrentCustomer();

  if (isLoading) {
    return <LoadingSpinner />;
  }

  if (error) {
    return <ErrorMessage error={error} />;
  }

  return (
    <View>
      <Text>Customer ID: {customer?.id}</Text>
      <Text>Active Subscriptions: {customer?.subscriptions?.length}</Text>
      {/* Display customer information */}
    </View>
  );
}

Platform-Specific Features

iOS-Only Features

Voidhash provides iOS-specific methods for managing subscriptions:

import { Platform } from "react-native";
import { voidhash } from "utils/voidhash/client";

export default function CustomerScreen() {
  const { client } = voidhash.useVoidhash();

  return (
    <View>
      {Platform.OS === "ios" && (
        <>
          <Button
            onPress={() => client.iosPresentCodeRedemptionSheet()}
            title="Redeem Code"
          />
          <Button
            onPress={() => client.iosShowManageSubscriptions()}
            title="Manage Subscriptions"
          />
        </>
      )}
    </View>
  );
}