WalletConnect Pay Integration via WalletKit
This guide provides all details needed to integrate WalletConnect Pay into a React Native wallet that already has WalletKit integrated. Pay is accessed throughwalletKit.pay.
Agent Guidance: Adapt, Don’t Copy
This plan is a reference, not a script. Each wallet has its own architecture, conventions, and patterns. Follow these principles:1. Match the Target Wallet’s Patterns
- Study the existing codebase first. Look at how similar features are implemented (e.g., how session requests are handled, how modals work, how state is managed).
- Follow existing conventions for file naming, folder structure, imports, and code style.
- Use the wallet’s existing UI components rather than creating new ones from scratch.
- Adapt the examples in this plan to fit the wallet’s architecture, not the other way around.
2. When in Doubt, Ask
If you’re uncertain about:- Which pattern to follow when multiple exist in the codebase
- Whether to create new infrastructure or extend existing
- How a specific wallet feature works
- The correct location for new files
3. Test Incrementally
Don’t implement everything at once. Verify each step:walletKit.payis accessible- Payment links are detected via
isPaymentLink - Modal/screen opens
- Payment options load
- Signing works
- Payment confirms
4. Validate After Every Step (CRITICAL)
After completing each step in the implementation:- Go back and review - Re-read the plan to ensure all requirements for that step were implemented correctly
- Check for linting errors - Run the linter on all modified/created files and fix any errors before proceeding
- Verify the code compiles - Ensure there are no TypeScript or build errors
- Test the functionality - If possible, verify the step works as expected before moving on
Prerequisites
The wallet must already have:@reown/walletkitintegrated and working@walletconnect/react-native-compatinstalled- WalletKit initialization in place
Required Package Versions (Canary)
walletKit.pay.
Architecture Overview
Step 1: Import isPaymentLink from WalletKit
WalletKit automatically provides pay functionality viawalletKit.pay. No additional configuration is needed.
Just add the isPaymentLink import to detect payment links:
Step 2: Add Payment Link Detection
Payment Link Detection
IMPORTANT: Always useisPaymentLink from WalletKit to detect payment links. Do NOT implement custom URL parsing or regex matching.
Current known formats (for reference only - may change):
isPaymentLink function handles all current and future formats internally, ensuring your integration remains compatible as the protocol evolves.
Use isPaymentLink from WalletKit
CRITICAL: Check ALL URI Entry Points
Payment link detection must be added to ALL places where URIs are processed:- QR Scanner - barcode scanning callback
- URI Paste/Input Field - text input with “Connect” button
- Deep Link Handler -
Linking.addEventListenerfor app URLs - Clipboard Paste - if the app supports paste-to-connect
walletKit.pair() and ensure each checks isPaymentLink(uri) first.
IMPORTANT: Payment links are HTTPS URLs (e.g., https://pay.walletconnect.com/?pid=xxx). Ensure the isPaymentLink() check happens BEFORE any generic HTTP/HTTPS URL handling that might open a browser.
Step 3: Implement Payment Flow
3.1 Handle Payment Link
3.2 Get Required Actions for Selected Option
3.3 Sign and Confirm Payment
IMPORTANT: Always try passing the raw JSON string first. This is the safest approach.3.4 Signing API Variations
Different wallet libraries have different signing APIs. The key insight is thatparsedParams[1] is already a complete, correctly-formatted JSON string. Try the simplest approach first.
Approach 1: Pass Raw JSON String (RECOMMENDED - Try This First)
This is the recommended approach. Many wallet signing APIs accept the typed data as a JSON string directly:Approach 2: Parse for APIs Requiring Objects (Fallback Only)
Only use this if Approach 1 fails. If your wallet API requires parsed objects (like ethers.js_signTypedData):
Common Pitfalls When Parsing
If you must parse the typed data, be aware of these issues:-
chainId as hex string: The domain may contain
chainId: "0x2105"(hex string) instead ofchainId: 8453(number). Some signing implementations require the number: -
Don’t guess primaryType: If your API needs
primaryType, extract it from the original data—don’t useObject.keys(types)[0]which returns the alphabetically first key (often wrong): -
String vs Object format: Test whether your signing API expects:
data: "{...}"(JSON string)data: {...}(parsed object) The wrong format may sign successfully but produce an invalid signature.
Step 4: Payment Modal/Screen UI
State Machine
State Definition
Required UI Components
- Loading View - Spinner with message
- Confirm View - Payment options list (with “Info required” badge on options with
collectData), selected option details, approve button - WebView Data Collection View - WebView form (if
selectedOption.collectData?.urlexists) - Confirming View - Spinner while signing and confirming
- Result View - Success or error message with close button
Display Elements
- Merchant name and icon from
paymentOptions.info.merchant - Payment amount from
option.amount.display - Network name and asset symbol
- ETA in seconds
Step 5: Utility Functions
Format Amount
Format Date Input (for collectData)
Validate Date
Core API Reference
Pay Client Methods (via walletKit.pay)
Account Format (CAIP-10)
Key Types
Architecture Adaptation Examples
Modal System Variations
React Native Modal (overlay):Wallet Library Variations
MetaMask KeyringController (recommended for MetaMask-based wallets):3.5 WebView Data Collection
WhenselectedOption.collectData?.url is present, display the URL in a WebView. The URL comes from the selected option’s collectData.url, which is already scoped to that option’s account. The hosted form handles rendering, validation, and T&C acceptance.
Install react-native-webview:
Important: When using the WebView approach, do not passcollectedDatatoconfirmPayment(). The WebView submits data directly to the backend.
Expo Considerations
Development Build Required
The Pay SDK uses native modules. Expo Go will NOT work.Troubleshooting
walletKit.pay is undefined
Cause: Native module not available. Solutions:- Verify
@walletconnect/react-native-compatis installed - iOS: Run
cd ios && pod install --repo-update - Android: Sync gradle and rebuild
- For Expo: Ensure using development build, not Expo Go
Payment Options Empty
Check:- Accounts array format is correct:
['eip155:chainId:address'] - Payment link URL is valid with
pidparameter - Wallet has supported chains configured
Signing Fails
Check:- Are you passing the raw JSON string? Try that first
- If parsing:
EIP712Domainis removed from types before signing - Params are parsed correctly (double-encoded JSON)
- Wallet address matches account used in
getPaymentOptions
”Recovered address does not match from address”
Cause: The signature was created with different data than the verifier expects. Debug steps:- Try passing raw string first: Use
parsedParams[1]directly without parsing/reconstructing - Check chainId format: Domain may have hex string (
"0x2105") instead of number (8453) - Check primaryType: Ensure it’s extracted from data, not guessed via
Object.keys(types)[0] - Check data format: Does your signing API expect a JSON string or parsed object?
parsedParams[1] string directly), only parse if your API specifically requires it.
”Missing or invalid. pair() uri#relay-protocol” Error
Cause: Payment link was passed towalletKit.pair() instead of being handled as payment.
Solution: Ensure isPaymentLink(uri) check happens BEFORE calling pair().
Payment Link Opens Browser Instead of Pay Modal
Cause: Payment links are HTTPS URLs, and your URI handling may have a generic HTTP/HTTPS handler that opens a browser before checking for payment links. Solution: Move theisPaymentLink(uri) check BEFORE any HTTP/HTTPS URL handling in your QR scanner, deep link handler, and paste handler.
File Checklist
When implementation is complete, verify: Modified Files:- WalletKit exports (re-export
isPaymentLink) - QR scanner handler (detect payment links BEFORE http/https handling)
- URI paste handler (detect payment links BEFORE http/https handling)
- Deep link handler (detect payment links)
- Modal/navigation system (register payment modal/screen)
- Payment modal/screen component
- Payment sub-components (IntroView, ConfirmView, etc.)
- Payment utility functions
- Payment state reducer (if using reducer pattern)
- WebView data collection component (using react-native-webview)
- iOS:
pod installcompleted - Android: Gradle sync completed
- No linting errors in modified files
- No TypeScript errors
- Code compiles successfully
- Functionality works as expected