npm package: @perkos/ui-payment
Description: x402 payment UI components for React - wallet agnostic
Author: PerkOS
Latest version: 1.0.0

# @perkos/ui-payment

x402 payment UI components for React - **wallet agnostic**.

This package provides payment UI components for x402 vendor apps. It works with any wallet provider (Thirdweb, Dynamic, Para, Wagmi, etc.) via the `WalletAdapter` interface.

## Installation

```bash
npm install @perkos/ui-payment

# Plus your wallet adapter
npm install @perkos/ui-payment-thirdweb  # for Thirdweb
npm install @perkos/ui-payment-dynamic   # for Dynamic
npm install @perkos/ui-payment-para      # for Para
```

## Quick Start

```tsx
import { PaymentButton } from "@perkos/ui-payment";
import { useThirdwebWallet } from "@perkos/ui-payment-thirdweb";

function Checkout({ paymentOptions }) {
  const wallet = useThirdwebWallet();

  return (
    <PaymentButton
      wallet={wallet}
      accepts={paymentOptions}
      onPaymentSigned={(envelope) => {
        // Retry your API request with the signed payment
        fetch("/api/paid-service", {
          headers: {
            "PAYMENT-SIGNATURE": btoa(JSON.stringify(envelope)),
          },
        });
      }}
      onError={(error) => console.error(error)}
    />
  );
}
```

## Components

### PaymentButton

Main payment UI component with:
- Multi-chain network selection
- USDC balance display
- Chain switching support
- EIP-712 payment signing

```tsx
<PaymentButton
  wallet={walletAdapter}
  accepts={acceptOptions}        // From 402 response
  defaultNetwork="avalanche"     // Optional default
  onPaymentSigned={handlePayment}
  onError={handleError}
  className="my-custom-class"
  disabled={false}
/>
```

### NetworkSelector

Dropdown for selecting payment network:

```tsx
<NetworkSelector
  accepts={networkOptions}
  defaultNetwork="base"
  value={selectedNetwork}
  onNetworkChange={handleChange}
  disabled={false}
/>
```

## Hooks

### usePaymentSigning

Core signing logic for EIP-712 payments:

```tsx
const { signPayment, isSigning, error } = usePaymentSigning({
  wallet,
  onSuccess: (envelope) => { /* ... */ },
  onError: (error) => { /* ... */ },
});

// Sign a payment
const envelope = await signPayment(acceptOption);
```

### useBalanceCheck

RPC-based USDC balance checking:

```tsx
const { balance, isLoading, refresh } = useBalanceCheck({
  address: wallet.address,
  selectedAccept: acceptOption,
  autoRefresh: true,
  refreshInterval: 30000,
});

// balance = { balance: "10.5000", hasEnough: true, requiredAmount: 0.05 }
```

## WalletAdapter Interface

To use with any wallet provider, implement this interface:

```typescript
interface WalletAdapter {
  address: `0x${string}` | undefined;
  chainId: number | undefined;
  isConnected: boolean;
  signTypedData: (params: SignTypedDataParams) => Promise<`0x${string}`>;
  switchChain?: (chainId: number) => Promise<void>;
}
```

### Custom Adapter Example

```typescript
import type { WalletAdapter } from "@perkos/ui-payment";

function useMyCustomWallet(): WalletAdapter {
  const myWallet = useMyWalletHook();

  return {
    address: myWallet.address,
    chainId: myWallet.chainId,
    isConnected: myWallet.isConnected,
    signTypedData: async (params) => {
      return myWallet.signTypedData(params);
    },
    switchChain: async (chainId) => {
      await myWallet.switchNetwork(chainId);
    },
  };
}
```

## AcceptOption Format

The `accepts` prop expects options from the x402 `PAYMENT-REQUIRED` header:

```typescript
interface AcceptOption {
  scheme: string;                    // "exact"
  network: string;                   // "eip155:43114" (CAIP-2)
  maxAmountRequired: string;         // "50000" (atomic units)
  resource: string;                  // "/api/ai/translate"
  payTo: `0x${string}`;              // Merchant address
  asset: `0x${string}`;              // USDC contract address
  extra?: {
    name?: string;                   // Token name for EIP-712
    version?: string;
    networkName?: string;            // "avalanche"
  };
}
```

## Supported Networks

| Network | Chain ID | CAIP-2 |
|---------|----------|--------|
| Avalanche | 43114 | eip155:43114 |
| Avalanche Fuji | 43113 | eip155:43113 |
| Base | 8453 | eip155:8453 |
| Base Sepolia | 84532 | eip155:84532 |
| Celo | 42220 | eip155:42220 |
| Celo Sepolia | 11142220 | eip155:11142220 |
| Ethereum | 1 | eip155:1 |

## Styling

The component uses inline styles by default. Override with `className`:

```tsx
<PaymentButton
  className="my-payment-button"
  // ...
/>
```

```css
.my-payment-button {
  /* Your custom styles */
}
```

## Constants & Utilities

```typescript
import {
  USDC_ADDRESSES,
  CHAIN_IDS,
  getChainId,
  getUSDCAddress,
  getNetworkDisplayName,
  toCAIP2Network,
  toLegacyNetwork,
} from "@perkos/ui-payment";
```

## Related Packages

- `@perkos/ui-payment-thirdweb` - Thirdweb wallet adapter
- `@perkos/ui-payment-dynamic` - Dynamic wallet adapter
- `@perkos/ui-payment-para` - Para wallet adapter
- `@perkos/middleware-x402` - Server-side payment verification

## License

MIT