This repository features a mobile wallet demo powered by Turnkey that integrates with WalletConnect Pay for merchant payments. Behind the scenes, it uses @turnkey/react-native-wallet-kit for embedded wallet management and signing, and @walletconnect/pay for the payment protocol.
With Turnkey, the wallet handles authentication and EIP-712 signing — WalletConnect Pay handles everything else: transaction construction, gas sponsorship (via 7702 paymaster), and on-chain broadcast. The wallet never holds or spends native ETH for gas.
Each end-user's wallet is fully self-custodial: Turnkey creates a dedicated sub-organization per user with a 1-of-1 root quorum, meaning only the authenticated user can authorize signing. The parent organization cannot access sub-organization private keys. Turnkey acts as the secure wallet infrastructure — key generation and signing happen within Turnkey's secure enclaves, but control belongs entirely to the end-user.
wcpay-turnkey-demo.mp4
Make sure you have Node.js installed locally; we recommend using Node v16+.
$ node --version # v16+
$ git clone https://github.com/MarkoKey/with-wcpay.git
$ cd with-wcpay/
$ cp .env.example .env
# Fill in your Turnkey and WalletConnect credentials in .env
$ npm install
$ npx expo prebuild --platform ios
$ npx expo run:iosTo configure the demo wallet you'll need the following:
| Variable | Description |
|---|---|
EXPO_PUBLIC_TURNKEY_ORGANIZATION_ID |
Your Turnkey organization ID from the Turnkey Dashboard |
EXPO_PUBLIC_TURNKEY_API_BASE_URL |
Turnkey API base URL (default: https://api.turnkey.com) |
EXPO_PUBLIC_TURNKEY_AUTH_PROXY_CONFIG_ID |
Auth Proxy configuration ID for email OTP |
EXPO_PUBLIC_TURNKEY_RPID |
Relying Party ID for passkey domain |
EXPO_PUBLIC_APP_SCHEME |
Deep link scheme for the app (default: wcpaydemo) |
EXPO_PUBLIC_WC_API_KEY |
WalletConnect Pay API key from the WalletConnect Dashboard |
TurnkeyProvider wraps the app at the root, providing auth state and a signMessage function to all screens:
Lines 49 to 52 in 1c3fbdb
WalletConnectPay is instantiated as a singleton client, initialized with your WalletConnect API key:
with-wcpay/constants/walletconnect.ts
Lines 8 to 14 in 1c3fbdb
Payment actions from WC Pay are signed via Turnkey's signMessage, bridging the WC Pay RPC format to EIP-712 signatures:
with-wcpay/lib/turnkey-signer.ts
Lines 27 to 105 in 1c3fbdb
The payment screen orchestrates the full flow — fetching options, identity verification, signing, and broadcast:
Lines 112 to 130 in 1c3fbdb
User ──▶ Email OTP ──▶ Turnkey creates sub-org + ETH wallet
│
▼
Scan WC Pay QR ──▶ Fetch payment options from WC Pay
│
▼
Confirm payment ──▶ Identity verification (if required)
│
▼
Turnkey signs EIP-712 ──▶ WC Pay broadcasts via 7702 paymaster ──▶ ✅ On-chain
- User authenticates via email OTP — Turnkey creates a sub-organization with an Ethereum wallet
- User scans a WalletConnect Pay QR code (or enters a payment link manually)
- App fetches payment options from WC Pay and displays merchant info
- If required, user completes identity verification (Travel Rule compliance) via WC Pay WebView
- User confirms — Turnkey signs the payment authorization, WC Pay handles gas and broadcasts on-chain
- Payment confirms — success screen
This demo is provided for testing and demonstration purposes only. It is not intended for production use. Use at your own risk.