Socket
Book a DemoInstallSign in
Socket

@cardql/react-native

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cardql/react-native

CardQL SDK for React Native applications with mobile-optimized features

1.0.1
latest
Source
npmnpm
Version published
Weekly downloads
2
Maintainers
1
Weekly downloads
 
Created
Source

@cardql/react-native

CardQL SDK for React Native applications with mobile-optimized features including offline support, secure storage, and native UI components.

Installation

npm install @cardql/react-native
# or
yarn add @cardql/react-native
# or
pnpm add @cardql/react-native

Additional Dependencies

For full functionality, you may want to install these optional dependencies:

# For secure storage (recommended)
npm install react-native-keychain
# or for Expo
npm install expo-secure-store

# For network status monitoring (recommended)
npm install @react-native-community/netinfo

# For persistent storage
npm install @react-native-async-storage/async-storage

Quick Start

1. Setup Provider

Wrap your app with the CardQL provider:

import React from "react";
import { CardQLProvider } from "@cardql/react-native";

function App() {
  return (
    <CardQLProvider
      config={{
        apiKey: "your-api-key",
        endpoint: "https://api.cardql.com/graphql",
      }}
      enableOfflineMode={true}
      enableSecureStorage={true}>
      <YourApp />
    </CardQLProvider>
  );
}

2. Use Hooks

Use CardQL hooks in your components:

import React from "react";
import { View, Text, TouchableOpacity, FlatList } from "react-native";
import { usePayments, useCreatePayment } from "@cardql/react-native";

function PaymentScreen() {
  const { data: paymentsData, loading, error } = usePayments();
  const createPayment = useCreatePayment({
    onSuccess: (data) => {
      console.log("Payment created:", data.createPayment);
    },
  });

  const handleCreatePayment = async () => {
    await createPayment.mutateAsync({
      amount: "10.00",
      currency: "USD",
      merchantID: "merchant_123",
      userID: "user_456",
    });
  };

  if (loading) return <Text>Loading...</Text>;
  if (error) return <Text>Error: {error.message}</Text>;

  return (
    <View>
      <TouchableOpacity
        onPress={handleCreatePayment}
        disabled={createPayment.loading}>
        <Text>{createPayment.loading ? "Creating..." : "Create Payment"}</Text>
      </TouchableOpacity>

      <FlatList
        data={paymentsData?.payments}
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => (
          <Text>
            {item.amount} {item.currency} - {item.status}
          </Text>
        )}
      />
    </View>
  );
}

3. Use Payment Sheet

Use the pre-built payment sheet:

import React, { useState } from "react";
import { View, TouchableOpacity, Text } from "react-native";
import { PaymentSheet } from "@cardql/react-native";

function CheckoutScreen() {
  const [showPaymentSheet, setShowPaymentSheet] = useState(false);

  return (
    <View>
      <TouchableOpacity onPress={() => setShowPaymentSheet(true)}>
        <Text>Pay Now</Text>
      </TouchableOpacity>

      <PaymentSheet
        visible={showPaymentSheet}
        onClose={() => setShowPaymentSheet(false)}
        merchantID="merchant_123"
        userID="user_456"
        onSuccess={(payment) => {
          console.log("Payment successful:", payment);
          // Navigate to success screen
        }}
        onError={(error) => {
          console.error("Payment failed:", error);
        }}
      />
    </View>
  );
}

Mobile-Specific Features

Offline Support

The React Native SDK includes built-in offline support:

import React from "react";
import { useOfflineQueue, useIsOnline } from "@cardql/react-native";

function OfflineAwareComponent() {
  const isOnline = useIsOnline();
  const { queue, addToQueue, processQueue } = useOfflineQueue();

  const handleOfflinePayment = async () => {
    if (!isOnline) {
      // Add to offline queue
      await addToQueue(CREATE_PAYMENT, {
        amount: "25.99",
        currency: "USD",
        merchantID: "merchant_123",
        userID: "user_456",
      });
    }
  };

  return (
    <View>
      <Text>Status: {isOnline ? "Online" : "Offline"}</Text>
      <Text>Queued Operations: {queue.length}</Text>
      {!isOnline && (
        <TouchableOpacity onPress={handleOfflinePayment}>
          <Text>Create Payment (Offline)</Text>
        </TouchableOpacity>
      )}
    </View>
  );
}

Secure Storage

API keys and sensitive data are automatically stored securely:

import React from "react";
import { useCardQL } from "@cardql/react-native";

function AuthComponent() {
  const { updateApiKey, clearStoredData } = useCardQL();

  const handleLogin = async (apiKey: string) => {
    // API key will be securely stored
    await updateApiKey(apiKey);
  };

  const handleLogout = async () => {
    // Clear all stored data
    await clearStoredData();
  };

  return (
    <View>
      <TouchableOpacity onPress={() => handleLogin("new-api-key")}>
        <Text>Login</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={handleLogout}>
        <Text>Logout</Text>
      </TouchableOpacity>
    </View>
  );
}

Network Status Monitoring

Monitor network connectivity:

import React from "react";
import {
  useNetworkStatus,
  useIsOnline,
  useIsOffline,
  useNetworkType,
} from "@cardql/react-native";

function NetworkStatusComponent() {
  const networkStatus = useNetworkStatus();
  const isOnline = useIsOnline();
  const isOffline = useIsOffline();
  const networkType = useNetworkType();

  return (
    <View>
      <Text>Connected: {isOnline ? "Yes" : "No"}</Text>
      <Text>Network Type: {networkType || "Unknown"}</Text>
      <Text>WiFi Enabled: {networkStatus.isWifiEnabled ? "Yes" : "No"}</Text>
    </View>
  );
}

API Reference

Provider Props

interface CardQLProviderProps {
  config: CardQLConfig;
  children: ReactNode;
  enableOfflineMode?: boolean; // Default: false
  enableSecureStorage?: boolean; // Default: true
  apiKeyStorageKey?: string; // Default: 'cardql_api_key'
}

Context Value

interface CardQLContextValue {
  cardql: CardQL;
  config: CardQLConfig;
  isOnline: boolean;
  enableOfflineMode: boolean;
  updateApiKey: (apiKey: string) => Promise<void>;
  clearStoredData: () => Promise<void>;
}

Offline Queue

const {
  queue, // Array of queued operations
  addToQueue, // Add operation to queue
  processQueue, // Process all queued operations
  clearQueue, // Clear the queue
  removeFromQueue, // Remove specific operation
  isProcessing, // Whether queue is being processed
} = useOfflineQueue({
  maxRetries: 3, // Maximum retry attempts
  retryDelay: 1000, // Delay between retries (ms)
  storageKey: "custom_queue_key",
});

Payment Sheet

<PaymentSheet
  visible={boolean}
  onClose={() => void}
  merchantID={string}
  userID={string}
  onSuccess={(payment) => void}
  onError={(error) => void}
  defaultAmount="10.00"
  defaultCurrency="USD"
  defaultDescription="Payment"
  // Styling props
  style={ViewStyle}
  headerStyle={ViewStyle}
  inputStyle={TextStyle}
  buttonStyle={ViewStyle}
  buttonTextStyle={TextStyle}
/>

Advanced Usage

Custom Storage Implementation

Replace the default storage with your own:

import { Storage } from "@cardql/react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";
import * as Keychain from "react-native-keychain";

class CustomSecureStorage implements Storage {
  async getItem(key: string): Promise<string | null> {
    try {
      const credentials = await Keychain.getInternetCredentials(key);
      return credentials ? credentials.password : null;
    } catch {
      return null;
    }
  }

  async setItem(key: string, value: string): Promise<void> {
    await Keychain.setInternetCredentials(key, key, value);
  }

  async removeItem(key: string): Promise<void> {
    await Keychain.resetInternetCredentials(key);
  }

  async clear(): Promise<void> {
    await Keychain.resetGenericPassword();
  }
}

// Use custom storage
export const customStorage = new CustomSecureStorage();

Offline-First Architecture

Build an offline-first app:

import React, { useEffect } from "react";
import {
  useOfflineQueue,
  useIsOnline,
  usePayments,
} from "@cardql/react-native";

function OfflineFirstComponent() {
  const isOnline = useIsOnline();
  const { queue, processQueue } = useOfflineQueue();
  const { data: payments, refetch } = usePayments({
    enabled: isOnline, // Only fetch when online
  });

  // Auto-sync when coming back online
  useEffect(() => {
    if (isOnline) {
      processQueue();
      refetch();
    }
  }, [isOnline, processQueue, refetch]);

  return (
    <View>
      {!isOnline && (
        <Text style={{ color: "orange" }}>
          Offline mode - {queue.length} operations queued
        </Text>
      )}
      {/* Your UI */}
    </View>
  );
}

Background Sync

Handle background synchronization:

import { useEffect } from "react";
import { AppState } from "react-native";
import { useOfflineQueue } from "@cardql/react-native";

function BackgroundSyncHandler() {
  const { processQueue } = useOfflineQueue();

  useEffect(() => {
    const handleAppStateChange = (nextAppState: string) => {
      if (nextAppState === "active") {
        // App came to foreground, process queue
        processQueue();
      }
    };

    const subscription = AppState.addEventListener(
      "change",
      handleAppStateChange
    );
    return () => subscription?.remove();
  }, [processQueue]);

  return null;
}

Error Handling

Handle mobile-specific errors:

import { Alert } from "react-native";
import { useCreatePayment } from "@cardql/react-native";

function PaymentWithErrorHandling() {
  const createPayment = useCreatePayment({
    onError: (error, variables) => {
      // Handle different error types
      if (error.code === "NETWORK_ERROR") {
        Alert.alert(
          "Network Error",
          "Please check your internet connection and try again.",
          [{ text: "OK" }]
        );
      } else if (error.code === "VALIDATION_ERROR") {
        Alert.alert("Invalid Payment", "Please check your payment details.", [
          { text: "OK" },
        ]);
      } else {
        Alert.alert(
          "Payment Failed",
          "An unexpected error occurred. Please try again.",
          [{ text: "OK" }]
        );
      }
    },
  });

  // Component implementation...
}

Styling

The PaymentSheet component can be fully customized:

const customStyles = {
  container: {
    backgroundColor: "#f5f5f5",
  },
  header: {
    backgroundColor: "#007bff",
    paddingVertical: 20,
  },
  title: {
    color: "#fff",
    fontSize: 20,
    fontWeight: "bold",
  },
  input: {
    borderRadius: 12,
    paddingHorizontal: 20,
    paddingVertical: 15,
    fontSize: 16,
    backgroundColor: "#fff",
    shadowColor: "#000",
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  button: {
    backgroundColor: "#28a745",
    paddingVertical: 18,
    borderRadius: 12,
  },
  buttonText: {
    fontSize: 18,
    fontWeight: "bold",
  },
};

<PaymentSheet
  style={customStyles.container}
  headerStyle={customStyles.header}
  inputStyle={customStyles.input}
  buttonStyle={customStyles.button}
  buttonTextStyle={customStyles.buttonText}
  // ... other props
/>;

Best Practices

1. Always Handle Offline States

// ✅ Good - Handle offline gracefully
function PaymentButton() {
  const isOnline = useIsOnline();
  const { addToQueue } = useOfflineQueue();
  const createPayment = useCreatePayment();

  const handlePayment = async (paymentData) => {
    if (isOnline) {
      await createPayment.mutateAsync(paymentData);
    } else {
      await addToQueue(CREATE_PAYMENT, paymentData);
      Alert.alert("Offline", "Payment queued for when you're back online");
    }
  };

  return (
    <TouchableOpacity onPress={() => handlePayment(data)}>
      <Text>{isOnline ? "Pay Now" : "Queue Payment"}</Text>
    </TouchableOpacity>
  );
}

2. Secure Storage for Sensitive Data

// ✅ Good - Use secure storage for API keys
<CardQLProvider
  config={{ endpoint: 'https://api.cardql.com/graphql' }}
  enableSecureStorage={true}
  apiKeyStorageKey="my_app_cardql_key"
>
  <App />
</CardQLProvider>

// ❌ Avoid - Don't hardcode API keys
<CardQLProvider
  config={{
    apiKey: 'hardcoded-key',  // Don't do this
    endpoint: 'https://api.cardql.com/graphql'
  }}
>
  <App />
</CardQLProvider>

3. Provide Feedback for Long Operations

function PaymentForm() {
  const createPayment = useCreatePayment();

  return (
    <View>
      <TouchableOpacity
        onPress={handleSubmit}
        disabled={createPayment.loading}
        style={[styles.button, createPayment.loading && styles.buttonDisabled]}>
        {createPayment.loading ? (
          <ActivityIndicator color="#fff" />
        ) : (
          <Text>Create Payment</Text>
        )}
      </TouchableOpacity>
    </View>
  );
}

Platform-Specific Considerations

iOS

  • Ensure you have the Keychain sharing capability enabled for secure storage
  • Test with different network conditions using Network Link Conditioner

Android

  • Add INTERNET permission in AndroidManifest.xml
  • Consider Android's battery optimization settings for background sync

License

MIT

Support

For support, please contact the CardQL team or visit our documentation.

Keywords

cardql

FAQs

Package last updated on 25 Jun 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.