+```tsx React — components/checkout.tsx
'use client'
import { createHttpTransport } from '@walletconnect/pay-core'
-import { useAppKitWalletProvider } from '@walletconnect/pay-appkit/react'
-import { browserClock, type PaymentOptionExtended } from '@walletconnect/pay-state'
+import { createAppKitSigner } from '@walletconnect/pay-appkit'
+import {
+ getPayAppKitInstance,
+ useAppKitWalletProvider,
+ usePayAppKit
+} from '@walletconnect/pay-appkit/react'
+import { browserClock } from '@walletconnect/pay-state'
import { usePaymentSession } from '@walletconnect/pay-react'
import { useMemo } from 'react'
-import { useAppKit } from '@/components/providers'
-import { createAppKitSigner } from '@/lib/signer'
export function Checkout({ paymentId }: { paymentId: string }) {
- const appKit = useAppKit()
+ // The provider constructs AppKit asynchronously; read the instance once it's ready.
+ const { isReady } = usePayAppKit()
+ const appKit = isReady ? getPayAppKitInstance() : undefined
+
+ // The wallet seam + a ready-made picker (list, search, pagination, QR URI).
const { wallet, wallets, wcUri, getWcUri } = useAppKitWalletProvider(appKit, {
wcPayUrl: typeof window !== 'undefined' ? window.location.href : undefined
})
- // Assemble the runtime seams. `signer` lives inside `seams`; `wallet` is passed separately.
+ // Assemble the runtime seams. The signer is one built-in call.
const seams = useMemo(
() => ({
transport: createHttpTransport({ baseUrl: '/api/wcp' }),
@@ -298,14 +216,49 @@ export function Checkout({ paymentId }: { paymentId: string }) {
[wallet]
)
- const { snapshot, connectWallet, selectOption, confirmSelection, submitInfoCapture } =
- usePaymentSession({ paymentId, seams, wallet })
+ const {
+ snapshot,
+ connectWallet,
+ disconnectWallet,
+ selectOption,
+ confirmSelection,
+ submitInfoCapture
+ } = usePaymentSession({ paymentId, seams, wallet })
- return {/* render per snapshot.state — see Step 7 */}
+ return {/* render per snapshot.state — see Step 5 */}
}
```
-Render it from a route, wrapped in your providers:
+```typescript JavaScript — main.ts
+import { createHttpTransport } from '@walletconnect/pay-core'
+import { createAppKitSigner, createAppKitWalletList } from '@walletconnect/pay-appkit'
+import { browserClock, createPaymentController } from '@walletconnect/pay-state'
+
+import { appKit } from './appkit'
+
+// The framework-neutral wallet-list controller: list / search / paginate / QR URI /
+// connect — and `walletList.wallet`, the seam the runtime drives.
+const walletList = createAppKitWalletList(appKit, {
+ wcPayUrl: window.location.href
+})
+const wallet = walletList.wallet
+
+const controller = createPaymentController({
+ paymentId,
+ wallet,
+ seams: {
+ transport: createHttpTransport({ baseUrl: '/api/wcp' }),
+ clock: browserClock,
+ signer: createAppKitSigner(wallet)
+ }
+})
+
+controller.subscribe(() => render(controller.getSnapshot()))
+controller.start()
+```
+
+
+In React, render the checkout from a route wrapped in your providers:
```tsx app/[paymentId]/page.tsx
import { Checkout } from '@/components/checkout'
@@ -317,15 +270,14 @@ export default async function PaymentPage({ params }: { params: Promise<{ paymen
}
```
-## Step 7 — Render the snapshot
+## Step 5 — Render the snapshot
-`snapshot.state` is a single string you switch on. Each state maps to one piece of UI; the named actions advance the flow.
+`snapshot.state` is a single string you switch on. Each state maps to one piece of UI; the named actions advance the flow. The logic is the same for React and JavaScript — the only difference is where the snapshot comes from (`usePaymentSession` vs `controller.getSnapshot()`).
```tsx
switch (snapshot.state) {
case 'ReadyForWallet':
- // Show the QR (snapshot is connecting-agnostic; QR comes from getWcUri/wcUri)
- // and a wallet picker. On pick:
+ // Show the QR (from getWcUri/wcUri) and a wallet picker. On pick:
return