npm package: @paykit/react
Description: Cross-chain payment widget for PayKit - Accept any input asset and deliver fixed target amount
Author: PayKit
Latest version: 0.1.3

# @paykit/react

Cross-chain payment widget for PayKit - Accept any input asset and deliver fixed target amount.

## Installation

Install the package and its peer dependencies:

```bash
npm install @paykit/react
npm install viem wagmi react react-dom
```

Or with yarn:

```bash
yarn add @paykit/react
yarn add viem wagmi react react-dom
```

Or with pnpm:

```bash
pnpm add @paykit/react
pnpm add viem wagmi react react-dom
```

**Note:** The package requires React 18 or 19, and React DOM 18 or 19 as peer dependencies.

## Quick Start

### 1. Import Required Components

```typescript
import { PaymentWidget, PaymentWidgetProvider, createSetupConfig } from '@paykit/react';
import '@paykit/react/styles.css';
```

### 2. Set Up the Provider

Wrap your application (or the section where you'll use the payment widget) with `PaymentWidgetProvider`:

```typescript
import { PaymentWidgetProvider, createSetupConfig } from '@paykit/react';
import { useWalletClient } from 'wagmi';
import type { SetupConfig } from '@paykit/react';

function App() {
  const { data: walletClient } = useWalletClient();
  
  const setupConfig = createSetupConfig({
    supportedChains: [
      {
        chainId: 1,
        name: 'Ethereum',
        rpcUrl: 'YOUR_RPC_URL',
        nativeCurrency: {
          name: 'Ether',
          symbol: 'ETH',
          decimals: 18,
        },
      },
      // Add more chains as needed
    ],
    walletClient: walletClient ?? undefined,
    useTestnet: false, // Set to true for testnet
  });

  return (
    <PaymentWidgetProvider setupConfig={setupConfig}>
      <YourAppContent />
    </PaymentWidgetProvider>
  );
}
```

### 3. Use the Payment Widget

```typescript
import { PaymentWidget } from '@paykit/react';
import type { PaymentConfig } from '@paykit/react';
import type { Address } from 'viem';

function CheckoutPage() {
  const paymentConfig: PaymentConfig = {
    targetTokenAddress: 'YOUR_TARGET_TOKEN_ADDRESS' as Address,
    targetChainId: 1, // Chain ID where the payment should be received
    targetAmount: BigInt('1000000000000000000'), // Amount in wei (1 token with 18 decimals)
    targetRecipient: 'YOUR_RECIPIENT_ADDRESS' as Address,
  };

  return (
    <PaymentWidget
      paymentConfig={paymentConfig}
      onPaymentComplete={(reference) => {
        console.log('Payment completed:', reference);
      }}
      onPaymentFailed={(error) => {
        console.error('Payment failed:', error);
      }}
    />
  );
}
```

## Configuration Options

### SetupConfig

The `SetupConfig` is used to configure shared infrastructure for all payment widgets in your application. Pass it to `PaymentWidgetProvider` via `createSetupConfig()`.

#### Required Properties

- **`supportedChains`** (`ChainConfig[]`): Array of blockchain networks that users can pay from. Each chain configuration includes:
  - `chainId`: The chain ID (number)
  - `name`: Human-readable chain name (string)
  - `rpcUrl`: RPC endpoint URL for the chain (string)
  - `nativeCurrency`: Object with `name`, `symbol`, and `decimals` for the native token
  - `rpcWsUrl` (optional): WebSocket RPC URL for real-time updates
  - `blockExplorerUrl` (optional): Block explorer URL for transaction links
  - `logoUrl` (optional): Logo URL for light theme
  - `logoUrlDark` (optional): Logo URL for dark theme

#### Optional Properties

- **`walletClient`** (`WalletClient | ConfiguredWalletClient`): Viem or wagmi wallet client instance. If using wagmi, you can get this via `useWalletClient()` hook.

- **`wagmiConfig`** (`WagmiConfig`): Wagmi configuration object. Required if you're using wagmi for wallet management.

- **`publicClients`** (`Record<number, PublicClient>`): Map of chain ID to public client instances. If not provided, default clients will be created from `supportedChains`.

- **`webSocketClients`** (`Record<number, PublicClient>`): Map of chain ID to WebSocket client instances for real-time updates. If not provided, will attempt to create from `supportedChains` if `rpcWsUrl` is available.

- **`integratorId`** (`Address`): Your integrator ID for tracking. Defaults to a zero integrator ID if not provided.

- **`apiUrl`** (`string`): Custom API URL for the Across Protocol SDK. Uses default if not provided.

- **`indexerUrl`** (`string`): Custom indexer URL for transaction indexing. Uses default if not provided.

- **`useTestnet`** (`boolean`): Whether to use testnet endpoints. Defaults to `false`.

- **`quoteRefreshMs`** (`number`): Interval in milliseconds for refreshing payment quotes. Defaults to a reasonable interval if not specified.

- **`wrappedTokenMap`** (`Record<number, Record<string, { wrapped: TokenConfig; native: TokenConfig }>>`): Mapping of wrapped tokens to their native equivalents for each chain. Used for handling native token wrapping.

- **`viemChains`** (`Chain[]`): Array of viem Chain objects. If not provided, will be created from `supportedChains`.

- **`tokenPricesUsd`** (`Record<number, Record<string, number>>`): Map of chain ID to token address to USD price. Used for displaying USD values in the UI.

- **`showUnavailableOptions`** (`boolean`): Whether to show payment options that cannot meet the target amount. Defaults to `false`.

- **`maxSwapQuoteOptions`** (`number`): Maximum number of swap quote options to display. Limits the number of alternative payment routes shown.

- **`toastHandler`** (`ToastHandler`): Custom toast notification handler for integrating with your application's toast system. If not provided, toast notifications will be silently ignored.

- **`appearance`** (`PaymentTheme`): Appearance configuration for theming:
  - `mode`: Theme mode (`'light' | 'dark'`). If not provided, will attempt to detect from DOM or media query.
  - `brandColor`: Primary brand color (string)
  - `accentColor`: Accent color (string)
  - `backgroundColor`: Background color (string)
  - `textColor`: Text color (string)
  - `borderRadius`: Border radius for UI elements (string)
  - `fontFamily`: Font family (string)
  - `card`: Card styling options (backgroundColor, textColor, borderColor)
  - `button`: Button class names (primaryClassName, secondaryClassName)
  - `className`: Additional CSS class name

- **`enableLogging`** (`boolean`): Enable or disable logging throughout the payment widget. When enabled (default), aggressive logging is used for debugging purposes. Set to `false` to disable all logging output.

### PaymentConfig

The `PaymentConfig` is used to configure individual payment widget instances. Each widget can have its own payment configuration.

#### Required Properties

- **`targetTokenAddress`** (`Address`): The address of the token that should be received on the destination chain.

- **`targetChainId`** (`number`): The chain ID where the payment should be received.

- **`targetAmount`** (`bigint`): The exact amount that should be received, specified in the smallest unit of the target token (e.g., wei for tokens with 18 decimals).

#### Optional Properties

- **`targetRecipient`** (`Address`): The address that will receive the payment. If not provided, will attempt to use the connected wallet address or fallback recipient.

- **`sameChainRecipient`** (`Address`): Recipient address specifically for same-chain payments (when origin and destination chains are the same). Takes precedence over `targetRecipient` for same-chain payments.

- **`crossChainRecipient`** (`Address`): Recipient address specifically for cross-chain payments (when origin and destination chains differ). Takes precedence over `targetRecipient` for cross-chain payments.

- **`fallbackRecipient`** (`Address`): Fallback recipient address used when `targetRecipient` is not available (e.g., when wallet is not connected).

- **`targetContractCalls`** (`Array<{ target: Address; callData: Hex; value: Amount }>`): Array of contract calls to execute on the destination chain after the deposit is received. Useful for executing additional logic after payment.

- **`maxSlippageBps`** (`number`): Maximum acceptable slippage in basis points (1 basis point = 0.01%). Used for swap quotes.

- **`appFee`** (`number`): Optional integrator fee (as a decimal, e.g., 0.01 for 1%) forwarded to the swap quote API.

- **`appFeeRecipient`** (`Address`): Address that collects the integrator fee when `appFee` is set.

- **`settlementToken`** (`SettlementTokenDescriptor | Address`): Optional descriptor indicating that the deposited target token is converted to another token via `targetContractCalls`. Can be a full descriptor object with `address`, `chainId`, `symbol`, `label`, and `description`, or just an address for automatic metadata resolution.

## PaymentWidget Props

- **`paymentConfig`** (`PaymentConfig`): **Required.** The payment configuration for this widget instance.

- **`onPaymentComplete`** (`(reference: string) => void`): Optional callback fired when payment is successfully completed. Receives a reference string.

- **`onPaymentFailed`** (`(error: string) => void`): Optional callback fired when payment fails. Receives an error message.

- **`className`** (`string`): Optional additional CSS class name for the widget container.

- **`historyOnly`** (`boolean`): If `true`, displays only the payment history view without the payment interface.

- **`hidePayNowButton`** (`boolean`): If `true`, hides the internal "Pay Now" button, allowing external control via the widget ref.

## Advanced Usage

### External Payment Control

You can control payment execution externally by using the widget ref:

```typescript
import { useRef } from 'react';
import { PaymentWidget } from '@paykit/react';
import type { PaymentWidgetRef } from '@paykit/react';

function CustomCheckout() {
  const widgetRef = useRef<PaymentWidgetRef>(null);

  const handleCustomPayment = async () => {
    if (widgetRef.current) {
      await widgetRef.current.executePayment();
    }
  };

  return (
    <div>
      <PaymentWidget
        ref={widgetRef}
        paymentConfig={paymentConfig}
        hidePayNowButton={true}
        onPaymentComplete={(ref) => console.log('Complete:', ref)}
      />
      <button onClick={handleCustomPayment}>
        Pay with Custom Button
      </button>
    </div>
  );
}
```

### Custom Toast Integration

Integrate with your application's toast system:

```typescript
import { createSetupConfig } from '@paykit/react';
import type { ToastHandler } from '@paykit/react';

const toastHandler: ToastHandler = {
  error: (message, duration) => {
    // Your error toast implementation
    return toastId;
  },
  success: (message, duration) => {
    // Your success toast implementation
    return toastId;
  },
  info: (message, duration) => {
    // Your info toast implementation
    return toastId;
  },
  dismiss: (id) => {
    // Dismiss specific toast
  },
  dismissAll: () => {
    // Dismiss all toasts
  },
};

const setupConfig = createSetupConfig({
  // ... other config
  toastHandler,
});
```

### Custom Theme

Customize the widget appearance:

```typescript
const setupConfig = createSetupConfig({
  // ... other config
  appearance: {
    mode: 'dark',
    brandColor: '#6366f1',
    accentColor: '#8b5cf6',
    borderRadius: '12px',
    fontFamily: 'Inter, sans-serif',
    card: {
      backgroundColor: '#1f2937',
      textColor: '#f9fafb',
      borderColor: '#374151',
    },
  },
});
```

## TypeScript Support

The package includes full TypeScript definitions. Import types as needed:

```typescript
import type {
  PaymentConfig,
  SetupConfig,
  PaymentWidgetProps,
  PaymentWidgetRef,
  ChainConfig,
  PaymentTheme,
  ToastHandler,
} from '@paykit/react';
```

## Requirements

- React 18 or 19
- React DOM 18 or 19
- Node.js environment with `fetch` and WebSocket support (Next.js provides this automatically)

## License

MIT

## Repository

[https://github.com/paykit-tech/react](https://github.com/paykit-tech/react)