Skip to main content Home Skills Automation & Agents chia-walletconnect chia-walletconnect moltbot
Telegram Web App for Chia wallet verification via WalletConnect and Sage. Enables cryptographic proof of wallet ownership through signature verification using MintGarden API.
bunx add-skill moltbot/skills -s chia-walletconnect archive backup clawdbot clawdhub skill
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:
cd skills/chia-walletconnect/webapp
vercel
# Copy the URL (e.g., https://chia-verify.vercel.app)
cd skills/chia-walletconnect/webapp
netlify deploy --prod
# Start Express server
npm start
# Expose via ngrok or reverse proxy
Step 2: Register with BotFather
Message @BotFather
Send /newapp or /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"
}
CHIP-0002 Methods (WalletConnect) Method Purpose chip0002_getPublicKeysFetch public keys from wallet chip0002_signMessageRequest message signature chia_getCurrentAddressGet 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 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
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
License
Links
Built with π± by Koba42 Corp