Chia WalletConnect Skill
Verify Chia wallet ownership via Telegram using WalletConnect integration with Sage Wallet.
What It Does
This skill provides a Telegram Mini App (Web App) that enables users to:
- •Connect their Sage Wallet via WalletConnect v2
- •Sign a challenge message cryptographically
- •Verify wallet ownership via MintGarden's signature verification API
- •Return verification status to your Telegram bot
Use Cases:
- •NFT-gated Telegram groups
- •Airdrop eligibility verification
- •Web3-style authentication
- •DAO voting authentication
- •Proof of token holdings
Architecture
/verify command → Web App button → WalletConnect → Sage signs → Verification
The user never leaves Telegram. The entire flow happens in-app via the Telegram Web App API.
Installation
# Install via ClawdHub clawdhub install chia-walletconnect # Install dependencies cd skills/chia-walletconnect npm install # Make CLI executable chmod +x cli.js
Deployment
Step 1: Deploy Web App
Deploy the webapp/ folder to a public HTTPS URL:
Vercel (Recommended):
cd skills/chia-walletconnect/webapp vercel # Copy the URL (e.g., https://chia-verify.vercel.app)
Netlify:
cd skills/chia-walletconnect/webapp netlify deploy --prod
Your Server:
# Start Express server npm start # Expose via ngrok or reverse proxy
Step 2: Register with BotFather
- •Message @BotFather
- •Send
/newappor/editapp - •Select your bot
- •Web App URL: Enter deployed URL
- •Short Name:
verify
Step 3: Add to Bot
Using Clawdbot Message Tool
// Send /verify command handler
message({
action: 'send',
target: chatId,
message: 'Click below to verify your Chia wallet:',
buttons: [[{
text: '🌱 Verify Wallet',
web_app: { url: 'https://your-app.vercel.app' }
}]]
});
Handling Verification Response
// In your bot's web_app_data handler
bot.on('web_app_data', async (msg) => {
const data = JSON.parse(msg.web_app_data.data);
const { address, message, signature, publicKey, userId } = data;
// Verify signature
const { verifySignature } = require('./skills/chia-walletconnect/lib/verify');
const result = await verifySignature(address, message, signature, publicKey);
if (result.verified) {
// Wallet verified! Grant access, record verification, etc.
message({
action: 'send',
target: msg.chat.id,
message: `✅ Wallet verified!\n\nAddress: ${address}`
});
// Store verification
// await db.saveVerification(userId, address);
} else {
message({
action: 'send',
target: msg.chat.id,
message: `❌ Verification failed: ${result.error}`
});
}
});
CLI Usage
The skill includes a CLI for testing:
# Generate challenge message node cli.js challenge xch1abc... telegram_user_123 # Verify signature manually node cli.js verify xch1abc... "message" "signature" "pubkey" # Validate address format node cli.js validate xch1abc... # Start development server node cli.js server
API Reference
MintGarden Signature Verification
Endpoint: POST https://api.mintgarden.io/address/verify_signature
{
"address": "xch1abc...",
"message": "Verify ownership of Chia wallet:...",
"signature": "hex_signature",
"pubkey": "hex_public_key"
}
Response:
{
"verified": true
}
CHIP-0002 Methods (WalletConnect)
| Method | Purpose |
|---|---|
chip0002_getPublicKeys | Fetch public keys from wallet |
chip0002_signMessage | Request message signature |
chia_getCurrentAddress | Get current receive address |
Verification Flow
1. User sends /verify to bot 2. Bot responds with Web App button 3. User taps button → Mini App opens in Telegram 4. Mini App initializes WalletConnect 5. User connects Sage Wallet 6. Challenge message generated (includes nonce + timestamp) 7. User signs message in Sage Wallet 8. Signature sent back to bot via Telegram.WebApp.sendData() 9. Bot verifies signature with MintGarden API 10. Bot confirms verification success/failure
Time: ~5-10 seconds for full flow (user-dependent)
Configuration
Environment Variables
Create .env in skill folder:
PORT=3000 WALLETCONNECT_PROJECT_ID=your-project-id MINTGARDEN_API_URL=https://api.mintgarden.io
Get WalletConnect Project ID
- •Visit WalletConnect Cloud
- •Create a new project
- •Copy your Project ID
- •Update in
webapp/app.js
Default Project ID:
The skill includes 6d377259062295c0f6312b4f3e7a5d9b (Dracattus reference). For production, use your own.
Security
What's Protected
- •✅ Challenge nonces prevent replay attacks
- •✅ Timestamps expire after 5 minutes
- •✅ MintGarden cryptographic verification
- •✅ No private keys ever requested
- •✅ HTTPS enforced by Telegram
Best Practices
- •Store verifications securely — Use encrypted database
- •Rate limit — Prevent spam verification attempts
- •Link to Telegram user ID — Prevent address spoofing
- •Implement cooldown — 1 verification per user per day
- •Log attempts — Audit trail for security
Production Checklist
- • Deploy to HTTPS URL (required by Telegram)
- • Use your own WalletConnect Project ID
- • Enable CORS only for your domain
- • Add rate limiting on webhook endpoints
- • Store verifications in persistent database
- • Implement retry logic for network errors
- • Set up monitoring/alerts
Files
chia-walletconnect/ ├── webapp/ │ ├── index.html # Telegram Web App UI │ ├── app.js # WalletConnect logic │ └── styles.css # Styling ├── lib/ │ ├── challenge.js # Challenge generation │ └── verify.js # MintGarden API client ├── server/ │ └── index.js # Express webhook server ├── cli.js # CLI interface ├── package.json # Dependencies ├── SKILL.md # This file └── README.md # Full documentation
Troubleshooting
Web App Doesn't Load
- •Verify HTTPS deployment (Telegram requires SSL)
- •Check URL is publicly accessible
- •Test URL directly in browser
- •Review browser console for errors
WalletConnect Connection Fails
- •Ensure Sage Wallet is latest version
- •Try manual URI paste instead of QR
- •Check WalletConnect Project ID is valid
- •Verify Sage supports WalletConnect v2
Signature Verification Fails
- •Ensure message format matches exactly
- •Confirm public key corresponds to address
- •Check MintGarden API is operational
- •Verify signature encoding (hex)
"No Public Key" Error
- •Some wallets don't expose pubkey via WalletConnect
- •Public key is optional for verification
- •Signature verification works without it
Examples
Simple Verification Bot
// Clawdbot skill handler
const { verifySignature } = require('./lib/verify');
// /verify command
if (message.text === '/verify') {
await message({
action: 'send',
target: message.chat.id,
message: 'Verify your Chia wallet:',
buttons: [[{
text: '🌱 Connect Wallet',
web_app: { url: process.env.WEB_APP_URL }
}]]
});
}
// Handle web app data
bot.on('web_app_data', async (msg) => {
const { address, message: challengeMsg, signature, publicKey } =
JSON.parse(msg.web_app_data.data);
const result = await verifySignature(address, challengeMsg, signature, publicKey);
if (result.verified) {
// Grant access
await grantAccess(msg.from.id, address);
await message({
action: 'send',
target: msg.chat.id,
message: `✅ Verified! Welcome, ${address.substring(0, 12)}...`
});
} else {
await message({
action: 'send',
target: msg.chat.id,
message: `❌ Verification failed`
});
}
});
NFT Gating
// Check if user owns specific NFT collection
const { verifySignature } = require('./skills/chia-walletconnect/lib/verify');
const mintGarden = require('./skills/mintgarden'); // Assume mintgarden skill exists
bot.on('web_app_data', async (msg) => {
const { address, message, signature, publicKey } =
JSON.parse(msg.web_app_data.data);
// Verify signature first
const verifyResult = await verifySignature(address, message, signature, publicKey);
if (!verifyResult.verified) {
return bot.sendMessage(msg.chat.id, '❌ Invalid signature');
}
// Check NFT ownership
const nfts = await mintGarden.getNFTsByAddress(address);
const hasRequiredNFT = nfts.some(nft =>
nft.collection_id === 'col1required...'
);
if (hasRequiredNFT) {
// Grant access to private group
await inviteToGroup(msg.from.id);
bot.sendMessage(msg.chat.id, '✅ Access granted! Check your invites.');
} else {
bot.sendMessage(msg.chat.id, '❌ You need a Wojak NFT to join!');
}
});
Performance
| Stage | Time |
|---|---|
| WalletConnect Init | ~1-2s |
| Connection Approval | User action |
| Sign Request | ~2-5s |
| MintGarden Verify | ~0.5-1s |
| Total | ~5-10s |
Dependencies
- •
@walletconnect/sign-client— WalletConnect v2 - •
@walletconnect/utils— WalletConnect helpers - •
@walletconnect/types— TypeScript types - •
express— Web server - •
node-fetch— HTTP client - •
cors— CORS middleware - •
dotenv— Environment config
Version
1.0.0
License
MIT — Koba42 Corp
Links
- •MintGarden API: https://api.mintgarden.io/docs
- •WalletConnect: https://docs.walletconnect.com/
- •Telegram Web Apps: https://core.telegram.org/bots/webapps
- •Sage Wallet: https://www.sagewallet.io/
- •CHIP-0002: https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0002.md
Built with 🌱 by Koba42 Corp