Secure WalletConnect integration for AI agents. Connect to user wallets as a DApp (Proposer) without ever handling private keys. Request transactions and sig...
---
name: walletconnect-requester
description: Secure WalletConnect integration for AI agents. Connect to user wallets as a DApp (Proposer) without ever handling private keys. Request transactions and signatures - users approve everything in their wallet. Zero custody, maximum security. Use when you need to interact with user wallets securely via WalletConnect v2.
metadata:
openclaw:
requires:
env:
- WC_PROJECT_ID (required): WalletConnect Cloud Project ID
- WC_METADATA_NAME (optional): DApp name shown in wallet
- WC_METADATA_URL (optional): DApp URL
- WC_METADATA_ICONS (optional): DApp icon URLs (comma-separated)
persistence:
path: ~/.walletconnect-requester/
files:
- sessions.json: Active WalletConnect sessions
- audit.log: Transaction audit log (masked sensitive data)
security_notes:
- WalletConnect URI contains symmetric key (symKey) - treat as sensitive
- Session tokens grant transaction request capability - protect accordingly
- Audit logs contain masked addresses and tx hashes - review before sharing
---
# WalletConnect Requester
> **Zero custody. Maximum security. User always in control.**
## Why This Skill?
Unlike `walletconnect-agent` which **holds private keys and auto-signs**, this skill takes a fundamentally different approach:
| | walletconnect-agent | walletconnect-requester (this skill) |
|---|---|---|
| **Private Keys** | ⚠️ Stored in agent | ✅ Never touches agent |
| **Signing** | ⚠️ Auto-signs everything | ✅ User approves each tx |
| **Security Model** | Custodial (agent has full control) | **Non-custodial (user has full control)** |
| **If Agent is Compromised** | ⚠️ Funds can be stolen | ✅ Funds are safe - no keys to steal |
**This is the safest way for AI agents to interact with Web3.**
## What This Does
- **Connect to user wallets** via WalletConnect v2
- **Request transactions** - user approves in their wallet
- **Request signatures** - user signs in their wallet
- **Zero private key exposure** - keys never leave the user's wallet
## Security Guarantees
```
┌─────────────────┐ ┌─────────────────┐
│ AI Agent │ │ User Wallet │
│ (Requester) │ ◄── WalletConnect ──► │ (Signer) │
│ │ Session │ │
└─────────────────┘ └─────────────────┘
│ │
│ 1. Request transaction │
│ ─────────────────────────────────► │
│ │
│ 2. User reviews & approves │
│ (in wallet UI) │
│ │
│ 3. Signed transaction │
│ ◄───────────────────────────────── │
│ │
▼ ▼
NO PRIVATE KEYS PRIVATE KEYS
NO AUTO-SIGN USER APPROVES
USER IN CONTROL EVERYTHING
```
## Installation
### Step 1: Install Dependencies
This skill requires Node.js dependencies. Install them globally or locally:
```bash
# Install dependencies
npm install @walletconnect/sign-client @walletconnect/core qrcode
```
### Step 2: Get WalletConnect Project ID
1. Go to [WalletConnect Cloud](https://cloud.walletconnect.com/)
2. Create a new project
3. Copy your **Project ID**
### Step 3: Set Environment Variable
```bash
export WC_PROJECT_ID="your_project_id_here"
```
### Step 4: Run the Skill
```bash
node scripts/wc-requester.js connect
```
---
## Quick Start
### Step 1: Create a Session
```bash
export WC_PROJECT_ID="your_project_id"
node scripts/wc-requester.js connect
```
Output:
```
WalletConnect URI: wc:abc123...@2?relay-protocol=irn&symKey=xyz
Scan this QR code with your wallet:
[QR CODE]
Waiting for wallet to connect...
```
### Step 2: Request a Transaction
```bash
node scripts/wc-requester.js request-tx \
--to 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 \
--data 0xa9059cbb... \
--value 0 \
--chain 8453
```
User sees in wallet:
```
Send 10 USDC to 0x1F3A...?
[Approve] [Reject]
```
### Step 3: Request a Signature
```bash
node scripts/wc-requester.js request-sign \
--message "Sign this message to verify ownership" \
--chain 8453
```
## Commands
### `connect` - Create WalletConnect Session
```bash
node scripts/wc-requester.js connect [options]
Options:
--chains <ids> Comma-separated chain IDs (default: 8453,1)
--methods <list> Comma-separated methods (default: eth_sendTransaction,personal_sign)
--qr <path> Generate QR code to file
--json Output as JSON
```
### `request-tx` - Request Transaction
```bash
node scripts/wc-requester.js request-tx --to <address> --data <hex> --value <wei> --chain <id>
```
### `request-sign` - Request Signature
```bash
node scripts/wc-requester.js request-sign --message <text> --chain <id>
# or for typed data
node scripts/wc-requester.js request-sign --typed-data <json> --chain <id>
```
### `sessions` - List Active Sessions
```bash
node scripts/wc-requester.js sessions
```
### `disconnect` - End Session
```bash
node scripts/wc-requester.js disconnect --topic <topic>
```
## Security Model
### What Agent CAN Do
- ✅ Request transactions (user must approve)
- ✅ Request signatures (user must approve)
- ✅ View connected wallet address
- ✅ View session metadata
### What Agent CANNOT Do
- ❌ Hold private keys
- ❌ Auto-sign anything
- ❌ Execute transactions without approval
- ❌ Access funds directly
### If Agent is Compromised
- ✅ Attacker cannot steal funds (no keys)
- ✅ Attacker cannot auto-sign transactions
- ✅ User can reject any suspicious request
- ✅ User can disconnect session anytime
### Local Data Persistence
This skill writes files to `~/.walletconnect-requester/`:
| File | Purpose | Sensitivity |
|------|---------|-------------|
| `sessions.json` | Active WalletConnect sessions | ⚠️ Contains session topics |
| `audit.log` | Transaction audit log | ⚠️ Contains masked tx hashes |
**Security recommendations:**
- Review `audit.log` before sharing
- Delete `sessions.json` when no longer needed
- Set appropriate file permissions: `chmod 600 ~/.walletconnect-requester/*`
### Sensitive Data Handling
| Data Type | How It's Handled |
|-----------|------------------|
| **WalletConnect URI** | Contains `symKey` - displayed once during connection, not logged |
| **Session tokens** | Stored locally in `sessions.json`, not transmitted externally |
| **Transaction hashes** | Logged in `audit.log` with masked addresses |
| **Private keys** | ❌ Never handled by this skill |
### Privacy Considerations
- WalletConnect URI (with `symKey`) is printed to stdout for QR code generation
- Audit logs mask full addresses (e.g., `0x8335...` instead of full address)
- No data is sent to external servers except WalletConnect relay network
## Configuration
### Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| `WC_PROJECT_ID` | Yes | WalletConnect Cloud Project ID |
| `WC_METADATA_NAME` | No | DApp name shown in wallet |
| `WC_METADATA_URL` | No | DApp URL |
| `WC_METADATA_ICONS` | No | DApp icon URL |
### Namespaces Configuration
The skill requests minimal permissions by default:
```json
{
"eip155": {
"chains": ["eip155:8453", "eip155:1"],
"methods": ["eth_sendTransaction", "personal_sign"],
"events": ["accountsChanged", "chainChanged"]
}
}
```
## Example Workflows
### Connect and Request Payment
```bash
# 1. Create session
node scripts/wc-requester.js connect --qr /tmp/qr.png
# User scans QR with MetaMask
# 2. Request USDC transfer
node scripts/wc-requester.js request-tx \
--to 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 \
--data 0xa9059cbb0000... \
--chain 8453
# User sees: "Send 10 USDC?" → Approves in wallet
# Returns: tx_hash
```
### Verify Wallet Ownership
```bash
# 1. Connect
node scripts/wc-requester.js connect
# 2. Request signature
node scripts/wc-requester.js request-sign \
--message "I own this wallet on March 9, 2026"
# User signs in wallet
# Returns: signature
```
## Comparison with Other Solutions
| Feature | This Skill | walletconnect-agent | MetaMask SDK |
|---------|-----------|---------------------|--------------|
| Private Key Storage | ❌ Never | ⚠️ In Agent | ❌ Never |
| Auto-sign | ❌ Never | ✅ Yes | ❌ No |
| User Approval Required | ✅ Always | ❌ No | ✅ Always |
| Multi-wallet Support | ✅ Any WC wallet | ✅ Any WC wallet | ❌ MetaMask only |
| Security Level | **Highest** | Medium | High |
| Best For | User-controlled tx | Automated trading | MetaMask users |
## Supported Wallets
Any wallet that supports WalletConnect v2:
- MetaMask Mobile
- Rainbow
- Trust Wallet
- Coinbase Wallet
- Ledger Live
- And 500+ more...
## Troubleshooting
### "No active session"
Run `connect` first to create a session.
### "User rejected request"
User declined in their wallet. Ask if they want to retry.
### "Session expired"
Sessions last 7 days by default. Reconnect to create a new session.
### "Unsupported chain"
User's wallet doesn't support the requested chain. Ask them to switch networks.
## Audit Log
All requests are logged (without sensitive data):
```
~/.walletconnect-requester/audit.log
{
"timestamp": "2026-03-09T02:00:00Z",
"action": "request_transaction",
"chain": 8453,
"to": "0x8335...",
"status": "approved",
"tx_hash": "0xabc123..."
}
```
## When to Use This vs walletconnect-agent
| Use This Skill When | Use walletconnect-agent When |
|--------------------|------------------------------|
| User must approve every tx | Fully automated trading |
| Maximum security required | You trust the agent completely |
| One-time or occasional tx | 24/7 unattended operation |
| User wants full control | User wants set-and-forget |
| Agent runs in untrusted env | Agent runs in secure env |
**When in doubt, use this skill.** It's always safer.
---
## License
MIT — Built with security as the #1 priority.
---
**Maintainer**: Web3 Investor Team
**Registry**: https://clawhub.com/skills/walletconnect-requesterdon't have the plugin yet? install it then click "run inline in claude" again.
added explicit procedure steps with input/output per step, identified network/timeout/expiry edge cases in decision points, specified JSON output schemas for all commands, clarified audit logging behavior, and documented when to reuse vs recreate sessions.
Use this skill when your agent needs to interact with user wallets on-chain without ever touching private keys. It implements the non-custodial WalletConnect v2 protocol where your agent acts as a "Proposer" (DApp) and the user's wallet acts as the "Responder" (Signer). Users approve every transaction and signature request directly in their wallet UI. This is the safest pattern for AI agents in Web3 because compromise of the agent cannot result in fund theft or unwanted transactions - the user wallet retains absolute control.
Environment Variables (setup required)
WC_PROJECT_ID (required): WalletConnect Cloud Project ID. Get it at https://cloud.walletconnect.com/ - create a new project and copy the ID.WC_METADATA_NAME (optional): DApp name displayed to user in wallet approval screen. Defaults to "AI Agent".WC_METADATA_URL (optional): DApp URL shown to user. Defaults to empty string.WC_METADATA_ICONS (optional): Comma-separated URLs for DApp icons. Defaults to empty list.External Connections
Node.js Dependencies
npm install @walletconnect/sign-client @walletconnect/core qrcode
Local Persistence
~/.walletconnect-requester/sessions.json: Stores active WalletConnect session topics and metadata.~/.walletconnect-requester/audit.log: Transaction request history with masked addresses and hashes.Context from User/Agent
Initialize client: Load @walletconnect/sign-client with WC_PROJECT_ID. Create metadata object from env vars (WC_METADATA_NAME, WC_METADATA_URL, WC_METADATA_ICONS). Failure: return error if WC_PROJECT_ID is unset or network unreachable.
Create session: Call signClient.connect() with namespace config (eip155 chains and methods). Output: WalletConnect URI with embedded symKey. Generate QR code if --qr flag provided. Display URI to user/agent for scanning.
Await wallet connection: Listen for session callback (session_connect event). Timeout: 5 minutes by default. On timeout: return error "wallet did not connect in time". On connection: extract accounts, chainId, sessionTopic from session object. Store session to ~/.walletconnect-requester/sessions.json with timestamp.
Request transaction (if user invokes request-tx): Build transaction object (to, data, value, chainId). Call signClient.request() with method eth_sendTransaction. Await user approval in wallet (timeout: 2 minutes). On rejection: return error with rejection reason. On approval: receive signed tx from wallet. Log to audit.log (masked address, tx hash, timestamp, status). Output: signed transaction object.
Request signature (if user invokes request-sign): For plain message: call signClient.request() with method personal_sign (or eth_sign). For EIP-712 typed data: call signClient.request() with method eth_signTypedData_v4. Await user approval in wallet (timeout: 2 minutes). On rejection: return error. On approval: receive signature string. Log to audit.log (message hash, signature, timestamp, status). Output: signature hex string.
List sessions: Load sessions.json. Parse and output active sessions (topic, accounts, expirationTime). Filter out expired sessions (compare to current time). Update file.
Disconnect: Accept sessionTopic parameter. Call signClient.disconnect() with topic. Remove entry from sessions.json. Log to audit.log (disconnect action, timestamp).
If WC_PROJECT_ID is not set: Skip initialization and return error "WC_PROJECT_ID environment variable not configured". Do not attempt relay connection.
If session already exists and is valid (not expired): Reuse existing session topic instead of creating a new one. Skip to step 4 or 5 directly. This avoids requiring the user to scan QR again.
If session is expired (>7 days old, default WalletConnect expiry): Remove from sessions.json and treat as no active session. Prompt user to reconnect via QR.
If network is unreachable (relay network down): Return error "WalletConnect relay network unreachable". Do not queue requests.
If user rejects transaction in wallet: Return error code REJECTED with rejection reason from wallet. Do not attempt to broadcast. Let agent/user decide on retry logic.
If transaction/signature request times out (>2 minutes, wallet does not respond): Cancel request and return error "request timeout". Session remains active.
If user switches chains in wallet mid-request: Wallet will typically reject request. Return error "chain mismatch - wallet on chainId X, request for chainId Y". Agent must re-request on correct chain or ask user to switch.
If audit.log cannot be written (permission denied, disk full): Log to stderr and continue. Do not block request/response. This prevents data unavailability from blocking transactions.
If sessions.json is corrupted (invalid JSON): Treat as empty, start fresh. Log error to stderr.
For connect command: Return JSON object:
{
"status": "success",
"uri": "wc:...",
"qr_code_path": "/tmp/qr.png",
"accounts": ["0xabc123..."],
"chainId": 8453,
"topic": "session_topic_...",
"expiration": "2026-03-16T02:00:00Z"
}
Or on failure:
{
"status": "error",
"error": "WC_PROJECT_ID not set"
}
For request-tx command: Return transaction receipt object or signed tx hex (depends on relay confirmations):
{
"status": "success",
"tx_hash": "0xabc123...",
"from": "0x...",
"to": "0x...",
"value": "0",
"data": "0x...",
"chainId": 8453,
"timestamp": "2026-03-09T02:00:00Z"
}
Or on rejection:
{
"status": "rejected",
"reason": "User declined transaction"
}
For request-sign command: Return signature hex:
{
"status": "success",
"signature": "0x...",
"message_hash": "0x...",
"timestamp": "2026-03-09T02:00:00Z"
}
For sessions command: Return array:
{
"status": "success",
"sessions": [
{
"topic": "session_...",
"accounts": ["0x..."],
"chainId": 8453,
"created": "2026-03-02T02:00:00Z",
"expires": "2026-03-09T02:00:00Z"
}
]
}
Audit log file (~/.walletconnect-requester/audit.log): Newline-delimited JSON, one entry per request:
{"timestamp":"2026-03-09T02:00:00Z","action":"request_transaction","chain":8453,"to":"0x8335...","status":"approved","tx_hash":"0xabc123..."}
{"timestamp":"2026-03-09T02:05:00Z","action":"request_signature","message_hash":"0xdef456...","status":"approved"}
{"timestamp":"2026-03-09T02:10:00Z","action":"request_transaction","chain":1,"to":"0x1f3a...","status":"rejected"}
request-tx. Screen shows recipient, calldata summary, value, and chain. User taps Approve. Agent receives signed transaction hex immediately.request-sign. Screen shows message or typed data to sign. User taps Sign. Agent receives signature hex immediately.audit.log grows with new entries each time a request succeeds or fails. Entries show timestamps, action type, recipient/hash (masked), and status.sessions.json contains active session with non-null topic and accounts array. Calling sessions command lists the session.credits: original author not declared in clawhub source; enriched per Implexa standards to include explicit decision points, edge cases, data formats, and outcome signals.