| title | metatags | sidebarTitle | ||
|---|---|---|---|---|
Wallet Pay Implementation for Wallets |
|
Wallet Implementation |
This guide shows wallet developers how to implement WalletConnect Pay to process payment requests during WalletConnect session establishment.
WalletConnect Pay allows merchants to request payments during the session connection flow. The payment request is included in the session proposal, and wallets can process the payment and return the transaction result when approving the session.
WalletConnect Pay is chain-agnostic and supports any asset on any blockchain network that can be identified using the CAIP-19 standard. This includes EVM chains, Solana, Bitcoin, Cosmos, and any other blockchain ecosystem.
- Merchant calls
provider.connect({ walletPay, ... })with payment details - Wallet receives session proposal containing payment request
- Wallet shows payment details to user
- User approves session (optionally with payment)
- Wallet processes payment and returns result in session approval
The walletPay object is located at proposal.params.requests.walletPay:
{
version: "1.0.0",
orderId?: string,
acceptedPayments: [{
asset: string, // CAIP-19 format: "eip155:1/erc20:0x..."
amount: string, // Hex-encoded: "0x186a0"
recipient: string // CAIP-10 format: "eip155:1:0x..."
}],
expiry?: number // UNIX timestamp
}EVM (Base network, USDC token):
{
"version": "1.0.0",
"acceptedPayments": [{
"asset": "eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "0x186a0",
"recipient": "eip155:8453:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
}],
"expiry": 1735689600
}Solana (USDC SPL token):
{
"version": "1.0.0",
"acceptedPayments": [{
"asset": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"amount": "0xf4240",
"recipient": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv"
}]
}Listen for session proposals and check for payment requests:
import { SignClientTypes } from '@walletconnect/types'
walletkit.on('session_proposal', async (proposal) => {
const walletPay = proposal?.params?.requests?.walletPay
if (walletPay) {
// Show payment approval UI
await handlePaymentProposal(proposal, walletPay)
} else {
// Regular session approval
await handleSessionProposal(proposal)
}
})Show the payment details from walletPay.acceptedPayments[0]:
- Asset (parse CAIP-19 to get token address)
- Amount (convert hex to decimal with token decimals)
- Recipient address
- Network/chain
Allow user to approve the session with or without processing the payment.
import { EngineTypes } from '@walletconnect/types'
import { buildApprovedNamespaces } from '@walletconnect/utils'
async function approveWithPayment(proposal, walletPay, shouldProcess) {
const namespaces = buildApprovedNamespaces({
proposal: proposal.params,
supportedNamespaces: YOUR_SUPPORTED_NAMESPACES
})
const responses = []
// Process payment if user approved
if (walletPay && shouldProcess) {
const result = await executePayment(walletPay)
responses.push(result)
}
// Approve session with payment result
await walletkit.approveSession({
id: proposal.id,
namespaces,
proposalRequestsResponses: responses
})
}Implement payment execution based on your wallet's architecture. The basic flow:
async function executePayment(walletPay: EngineTypes.WalletPayParams) {
const payment = walletPay.acceptedPayments[0]
// Parse payment details
const [chainId, assetType, assetAddress] = parseAsset(payment.asset)
const recipientAddress = payment.recipient.split(':')[2]
// Execute transfer (implementation depends on your wallet)
const txHash = await transferToken(
assetAddress,
recipientAddress,
payment.amount,
chainId
)
// Return result
return {
version: walletPay.version,
orderId: walletPay.orderId,
txid: txHash,
recipient: payment.recipient,
asset: payment.asset,
amount: payment.amount
}
}Return this structure in proposalRequestsResponses:
{
version: string, // Echo from request
orderId?: string, // Echo from request
txid: string, // Transaction hash
recipient: string, // CAIP-10 recipient
asset: string, // CAIP-19 asset
amount: string // Hex-encoded amount
}The merchant receives this in session.walletPayResult[0].
WalletConnect Pay uses CAIP standards to ensure chain-agnostic compatibility across all blockchain networks.
All assets use CAIP-19 identifiers:
{chainNamespace}:{chainId}/{assetNamespace}:{assetReference}
Examples across different chains:
| Chain | Example Asset |
|---|---|
| Ethereum (USDC) | eip155:1/erc20:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 |
| Base (USDC) | eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| Optimism (USDC) | eip155:10/erc20:0x7F5c764cBc14f9669B88837ca1490cCa17c31607 |
| Polygon (USDC) | eip155:137/erc20:0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174 |
| Arbitrum (USDC) | eip155:42161/erc20:0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8 |
| Solana (USDC) | solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
WalletConnect Pay supports any asset on chains with CAIP-19 specifications, including all EVM chains and Solana.
All recipients use CAIP-10 account identifiers:
{chainNamespace}:{chainId}:{address}
Examples:
- Ethereum:
eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb - Base:
eip155:8453:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb - Solana:
solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv
Amounts are hex-encoded in the asset's smallest unit (varies by chain):
// EVM tokens (e.g., 10 USDC with 6 decimals)
"0x" + (10 * 10**6).toString(16) // "0x989680"
// Solana tokens (e.g., 1 USDC with 6 decimals)
"0x" + (1 * 10**6).toString(16) // "0xf4240"Handle common scenarios:
- Expired requests: Check
walletPay.expiryagainst current timestamp - Insufficient balance: Validate before attempting transfer
- User rejection: Allow session approval without payment
- Transaction failures: Catch errors and optionally reject session
Test with the reference implementation:
git clone https://github.com/reown-com/web-examples.git
cd web-examples
git checkout chore/wallet-pay-dapp
cd advanced/dapps/walletconnect-pay-dapp
npm install && npm run dev