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 person'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 Person Data

Current Person Information

Use the useCurrentPerson hook to access the current person's subscription and perk information:

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

export default function PersonScreen() {
  const { data: person, isLoading, error } = voidhash.useCurrentPerson();

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

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

  return (
    <View>
      <Text>Person ID: {person?.id}</Text>
      <Text>Active Subscriptions: {person?.subscriptions?.length}</Text>
      {/* Display person 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 PersonScreen() {
  const { client } = voidhash.useVoidhash();

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