## Documentation Index

Fetch the complete documentation index at: [/llms.txt](https://docs.walletconnect.com/llms.txt)

Use this file to discover all available pages before exploring further.

The runtime is split into layered packages. Each is independently consumable, and lower layers never depend on higher ones — so you can take only what you need.

| Package | Role | Depends on |
| --- | --- | --- |
| [`@walletconnect/pay-core`](https://www.npmjs.com/package/@walletconnect/pay-core) | Engine API client — contract types, CAIP utilities, the browser `Transport` seam (`createHttpTransport`), and the server-side `createEngineClient` that holds your API key. The foundation. | — |
| [`@walletconnect/pay-state`](https://www.npmjs.com/package/@walletconnect/pay-state) | The headless runtime — the payment state machine, orchestration, the injectable **seam** contracts, the session factory, and the public `PaymentSnapshot` view-model. No React, no HTTP client, no wallet SDK. | `pay-core` |
| [`@walletconnect/pay-react`](https://www.npmjs.com/package/@walletconnect/pay-react) | Thin React binding — `usePaymentSession` returns the snapshot plus domain actions. Zero state-machine leak. | `pay-state` |
| [`@walletconnect/pay-appkit`](https://www.npmjs.com/package/@walletconnect/pay-appkit) | Reown AppKit adapter — implements the `WalletProvider` seam over a Reown AppKit instance (plus the Solana web3 loader). A `/react` subpath ships the wallet-connection hook. | `pay-state` |

##  `@walletconnect/pay-core`

The foundation: Engine contract types, CAIP utilities, and the `Transport` seam. Zero runtime dependencies. Two entry points — a browser-safe main entry and a server-only `/server` entry that holds the key.

### Browser entry — `@walletconnect/pay-core`

```
import { createHttpTransport, type Transport, type HttpTransportConfig } from '@walletconnect/pay-core'

interface HttpTransportConfig {
  baseUrl?: string      // default '/api/wcp'
  fetch?: typeof fetch
  timeoutMs?: number    // default 30_000
}

function createHttpTransport(config?: HttpTransportConfig): Transport
```

The `Transport` contract (the seam the runtime depends on) — five methods, each resolving to an `EngineResponse<T>` envelope (never throwing):

```
interface Transport {
  getPayment(paymentId): Promise<EngineResponse<GetPaymentResponse>>
  getPaymentOptions(paymentId, request): Promise<EngineResponse<GetPaymentOptionsResponseExtended>>
  fetchOptionActions(paymentId, request): Promise<EngineResponse<EngineBuildData>>
  confirmPayment(paymentId, request): Promise<EngineResponse<unknown>>
  getPaymentStatus(paymentId): Promise<EngineResponse<GetPaymentStatusResponse>>
}
```

Also exported: all Engine contract types (`GetPaymentResponse`, `PaymentOptionExtended`, `Amount`, `CollectData`, `PaymentStatus`, …), CAIP utilities (`parseCaip2`, `parseCaip10`, …), and transport error helpers (`TRANSPORT_ERROR_CODES`, `isAbortError`, `DEFAULT_TIMEOUT_MS`).

### Server entry — `@walletconnect/pay-core/server`

```
import { createEngineClient, type EngineClient, type EngineClientConfig, DEFAULT_VERSION } from '@walletconnect/pay-core/server'

interface EngineClientConfig {
  apiUrl: string        // e.g. https://staging.api.pay.walletconnect.org (no trailing slash)
  apiKey: string        // your Gateway Api-Key — keep secret, server-side only
  version?: string      // WCP API version; defaults to DEFAULT_VERSION
  fetch?: typeof fetch
  timeoutMs?: number    // default 30_000
}

function createEngineClient(config: EngineClientConfig): EngineClient
```

`EngineClient` exposes the same five methods as `Transport`, but attaches the secret `Api-Key` and `Wcp-Version` headers and calls the Engine directly. Use it only on the server.

##  `@walletconnect/pay-state`

The headless runtime: the payment state machine, the injectable seam contracts, the framework-agnostic `PaymentController`, the signing strategies, and the public `PaymentSnapshot` view-model.

### `createPaymentController`

The framework-agnostic binding (the React hook wraps this). Use it directly in a non-React host.

```
import { createPaymentController, type PaymentController, type PaymentControllerOptions } from '@walletconnect/pay-state'

interface PaymentControllerOptions {
  paymentId: string
  seams: PaymentSessionSeams        // { transport, clock, signer?, telemetry? }
  wallet: WalletProvider
  initialPayment?: GetPaymentResponse
  signingTimeoutMs?: number
  onMachineEvent?: MachineEventObserver  // read-only analytics observer
}

function createPaymentController(options: PaymentControllerOptions): PaymentController
```

```
interface PaymentController {
  getSnapshot(): PaymentSnapshot
  subscribe(listener: () => void): () => void
  start(): void
  destroy(): void
  // domain actions (see the React hook below for the full list)
  connectWallet(wallet, namespace?, options?): void
  // …
}
```

### Seams

The runtime reaches the outside world only through these contracts:

```
interface PaymentSessionSeams {
  transport: Transport          // Engine calls (from pay-core)
  clock: Clock                  // intervals + page visibility (for status polling)
  signer?: Signer               // signing capability — required for an end-to-end payment
  telemetry?: Telemetry         // optional analytics breadcrumbs
}

interface WalletProvider {
  getAccounts(): Partial<Record<Namespace, NamespaceAccount | undefined>>
  getProvider<T extends Namespace>(network: Caip2 & { namespace: T }): ProviderForNamespace<T> | null
  connect(wallet: WalletRef, namespace: Namespace, options?: WalletConnectOptions): Promise<void>
  disconnect(namespace?: Namespace): Promise<void>
  switchNetwork(caipNetworkId: string): Promise<void>
  subscribe(listener: () => void): () => void
}

interface Signer {
  signActions(option: PaymentOptionExtended, range?: ActionRange): Promise<SignPaymentResult[]>
}
```

Browser defaults are provided so you only have to inject `transport`, `wallet`, and `signer`:

```
import { browserClock, noopTelemetry, browserDefaults } from '@walletconnect/pay-state'
```

### Signing strategies

AppKit hosts don’t need these directly — `@walletconnect/pay-appkit` exports a zero-config `createAppKitSigner(wallet)` that wraps them with the bundled Solana codec. These are the low-level primitives, for a custom wallet integration.

```
import { EvmSigningStrategy, SolanaSigningStrategy, signOptionActions } from '@walletconnect/pay-state'

// Dispatch each of an option's actions to the matching strategy:
signOptionActions(option: PaymentOptionExtended, strategies: SigningStrategy[], range?: ActionRange): Promise<SignPaymentResult[]>
```

### `PaymentSnapshot`

The public, serializable view-model. `state` is one of:

| Group | States |
| --- | --- |
| Loading | `Initializing` |
| Wallet | `ReadyForWallet`, `ConnectingWallet` |
| Options | `LoadingOptions`, `OptionsReady`, `NoOptions`, `OptionSelected` |
| Compliance | `InformationCapture` |
| Approval | `RequiresApproval`, `AwaitingWalletApproval`, `WaitingForConfirmation` |
| Terminal | `Succeeded`, `Failed`, `PaymentExpired`, `PaymentCancelled`, `InvalidPayment`, `SanctionedUser` |

```
interface PaymentSnapshot {
  state: PaymentState
  payment?: GetPaymentResponse
  options: PaymentOptionExtended[]
  selectedOption?: PaymentOptionExtended
  collectData?: CollectData | null
  wallet: { isConnected: boolean; accounts: string[] }
  requiresApproval: boolean
  signingError?: { code: string; message?: string }
  isQuoteExpired: boolean
  profileId?: string
  profileNotFound: boolean
  // …diagnostic fields
}
```

##  `@walletconnect/pay-react`

A single hook — `usePaymentSession` — a `useSyncExternalStore`-based binding over the controller. SSR-safe, tear-free, zero XState leak.

```
import { usePaymentSession, type UsePaymentSessionOptions, type PaymentSessionApi } from '@walletconnect/pay-react'

function usePaymentSession(options: UsePaymentSessionOptions): PaymentSessionApi
```

`UsePaymentSessionOptions` matches `PaymentControllerOptions` (`paymentId`, `seams`, `wallet`, `initialPayment?`, `signingTimeoutMs?`, `onMachineEvent?`). The return is `{ snapshot }` plus the named actions:

| Action | Drives |
| --- | --- |
| `connectWallet(wallet, namespace?, options?)` | Begin connecting a wallet |
| `disconnectWallet(namespace?)` | Disconnect one namespace, or all |
| `selectOption(option, rank)` | Pick a payment option |
| `confirmSelection()` | Confirm and move toward signing |
| `unselectOption()` | Return to the option list |
| `submitInfoCapture(data)` | Submit collected KYC/contact data |
| `navigateBack()` | Step back |

Plus a **host-orchestration channel** for signals the runtime can’t observe itself — `refreshOptions`, `notifyQuoteExpired`, `acknowledgeQuoteExpiry`, `markUserSanctioned`, `setProfileLookup`, `notifyPaymentExpired`, `failWalletConnection`. Most gateways won’t need these to start.

##  `@walletconnect/pay-appkit`

The Reown AppKit adapter — it owns the entire AppKit setup so a host stays `@reown/*`-free. It constructs the instance, implements the `WalletProvider` seam over it, provides a zero-config `Signer`, and ships a headless wallet-picker controller. The main entry is framework-neutral; the React provider + hooks live on `/react`.

### Main entry — `@walletconnect/pay-appkit`

```
import {
  createPayAppKit,              // ({ projectId, metadata, themeVariables? }) => PayAppKit  (one-call setup)
  createAppKitSigner,           // (wallet) => Signer  (zero-config, bundles the Solana codec)
  createAppKitWalletList,        // (appKit, options?) => AppKitWalletList  (framework-neutral picker)
  createAppKitWalletProvider,   // (appKit, options?) => WalletProvider
  SUPPORTED_NETWORKS, EVM_NETWORKS, // the WC-owned network set (baked in, not host config)
  loadSolanaWeb3,               // lazy @solana/web3.js codec loader for the Solana signing strategy
  applyPlacements, resolvePlacements, // wallet-ordering helpers
  type AppKit,                  // re-exported AppKit instance type — don't import @reown/appkit directly
  type PayAppKit, type CreatePayAppKitOptions, type PayAppKitMetadata,
  type WalletListItem, type ConnectedWallet, type WalletListState, type WalletListOptions
} from '@walletconnect/pay-appkit'
```

`createPayAppKit` builds the instance with the WC-owned networks + adapters in headless mode. It’s **client-only and async** — `await payAppKit.whenReady()`, then read `getInstance()` / `getWagmiConfig()` / `getHooks()` / `getError()` / `isInitialized()`.`createAppKitWalletList` returns a controller — `wallet` (the seam), `getState()`, `subscribe()`, `fetchWallets()`, `search()`, `loadMore()`, `getWcUri()` — for non-React hosts.

### React entry — `@walletconnect/pay-appkit/react`

The zero-config provider that owns AppKit’s construction + the Wagmi/Query tree + an SSR-safe context, plus the state hook and the imperative instance accessor:

```
import {
  PayAppKitProvider,     // <PayAppKitProvider projectId metadata themeVariables? queryClient?>
  usePayAppKit,          // SSR-safe hook: isReady / account / network / walletConnection / connect / disconnect / …
  getPayAppKitInstance,  // module-level accessor to the same AppKit instance (for non-hook consumers)
  useAppKitWalletProvider,
  type AppKitWalletProviderHandle,
  type UseAppKitWalletProviderOptions
} from '@walletconnect/pay-appkit/react'

function useAppKitWalletProvider(appKit: AppKit | undefined, options?: UseAppKitWalletProviderOptions): AppKitWalletProviderHandle
```

`useAppKitWalletProvider`’s handle extends `WalletListState` and adds `wallet` (the seam to hand `usePaymentSession`), `searchQuery`/`setSearchQuery` (debounced), `fetchWallets`, `loadMore`, and `getWcUri` for the pairing QR.
