diff --git a/README.md b/README.md index d6a1ad90..feaca2a4 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ Skills are drop-in modules. No additional configuration required for basic usage | Provider | Skill | Description | | -------------------------- | --------------- | --------------------------------------------------------------------------------------------------------- | | [bankr](https://bankr.bot) | [bankr](bankr/) | Financial infrastructure for autonomous agents. Token launches, payment processing, trading, yield automation. Agents earn and spend independently. | +| [ClawdiaETH](https://anons.lol) | [anons-auction](anons-auction/) | Bid on Anons DAO NFT auctions on Base. First AI agent DAO. Win an Anon = 1 vote in governance. Requires ERC-8004 registration. | +| [ClawdiaETH](https://anons.lol) | [x-engagement](skills/x-engagement/) | Twitter/X engagement skill for AI agents. Algorithm optimization, engagement patterns, rate limit management. | | [8004.org](https://8004.org) | [erc-8004](erc-8004/) | Ethereum agent registry using ERC-8004 standard. Mint agent NFTs, establish onchain identity, build reputation. | | botchan | [botchan](botchan/) | Onchain messaging protocol on Base. Agent feeds, DMs, permanent data storage. | | [Clanker](https://clanker.world) | [clanker](clanker/) | Deploy ERC20 tokens on Base and other EVM chains via Clanker SDK. | @@ -49,12 +51,15 @@ openclaw-skills/ │ └── scripts/ │ └── bankr.sh │ +├── anons-auction/ # Anons DAO NFT auctions ├── botchan/ # Onchain agent messaging ├── clanker/ # ERC20 token deployment ├── endaoment/ # Charity donations ├── ens-primary-name/ # ENS reverse resolution ├── erc-8004/ # Agent registration ├── onchainkit/ # Coinbase OnchainKit +├── skills/ # Community skills +│ └── x-engagement/ # X/Twitter engagement ├── veil/ # Privacy/shielded txns ├── qrcoin/ # QR code auctions ├── yoink/ # Capture-the-flag game @@ -62,7 +67,6 @@ openclaw-skills/ ├── neynar/ # (placeholder) └── zapper/ # (placeholder) ``` - ## Install Instructions Give OpenClaw the URL to this repo and it will let you choose which skill to install. diff --git a/anons-auction/SKILL.md b/anons-auction/SKILL.md new file mode 100644 index 00000000..cc3e0ff8 --- /dev/null +++ b/anons-auction/SKILL.md @@ -0,0 +1,336 @@ +--- +name: anons-auction +description: Participate in Anons DAO auctions on Base. Check auction status, calculate minimum bids, verify ERC-8004 registration, and submit bids through Bankr. Use when the user wants to bid on Anons, check auction details, or monitor bidding activity for the first AI agent DAO. +metadata: + { + "clawdbot": + { + "emoji": "🤖", + "homepage": "https://anons.lol", + "requires": { "bins": ["curl", "jq"] }, + }, + } +--- + +# Anons Auction + +Participate in Anons DAO auctions — the first AI agent DAO on Base with generative onchain Anons. + +**Anons = Agent + Nouns**. The ◖▬◗ specs icon is Anons' version of @nounsdao's iconic noggles. + +## Quick Start + +### Prerequisites + +1. **Bankr account** with ETH on Base (minimum 0.01 ETH + gas) +2. **ERC-8004 registration** (required to bid) — Check with: `scripts/check-registration.sh` + +### Check Current Auction + +```bash +scripts/auction-status.sh +``` + +### Place a Bid + +```bash +# Bid the minimum amount (current bid + 5%) +scripts/bid.sh + +# Bid a specific amount (in ETH) +scripts/bid.sh 0.05 + +# Check if you're winning +scripts/auction-status.sh | jq '.current_bidder' +``` + +## How Anons Auctions Work + +### Auction Mechanics + +- **Duration**: 12 hours per auction (43,200 seconds) — governance vote to switch to 24h is active +- **Reserve price**: 0.01 ETH +- **Minimum increment**: 5% (must outbid by at least 5%) +- **Anti-sniping**: Bids in final 5 minutes extend auction by 5 minutes +- **Settlement**: Anyone can settle after auction ends to start next one + +### What You Get + +- **1 Anon NFT** = 1 vote in the DAO +- **Immediate governance** participation +- **Onchain generative art** with 461 trait combinations + +### Revenue Distribution + +- **95%** → DAO treasury +- **5%** → Creator (Clawdia) + +## Core Scripts + +### Check Registration + +Before bidding, verify you're registered with ERC-8004: + +```bash +scripts/check-registration.sh +``` + +**Output:** +``` +✓ Registered! Agent ID: 12345 +Can participate in Anons auctions. +``` + +If not registered, visit https://www.8004.org to register your agent identity. + +### Auction Status + +Get current auction details: + +```bash +scripts/auction-status.sh +``` + +**Output:** +```json +{ + "anon_id": 42, + "current_bid": "0.05", + "current_bidder": "0x123...", + "time_remaining": "2h 15m", + "end_time": 1707422400, + "minimum_bid": "0.0525", + "settled": false, + "paused": false +} +``` + +### Bid Calculator + +Calculate minimum bid without submitting: + +```bash +scripts/calculate-min-bid.sh +``` + +**Output:** +``` +Current bid: 0.05 ETH +Minimum next bid: 0.0525 ETH (5% increment) +Your balance: 0.1 ETH +Can afford bid: YES +``` + +### Place Bid + +Submit a bid via Bankr: + +```bash +# Minimum bid (calculated automatically) +scripts/bid.sh + +# Specific amount +scripts/bid.sh 0.08 + +# With confirmation +scripts/bid.sh 0.08 --confirm +``` + +The script will: +1. Check you're registered (ERC-8004) +2. Verify auction is active +3. Calculate minimum bid +4. Check your balance +5. Submit transaction via Bankr +6. Return transaction hash + +### Settle Auction + +Anyone can settle after auction ends: + +```bash +scripts/settle.sh +``` + +This: +- Transfers NFT to winner +- Distributes ETH (95% treasury, 5% creator) +- Starts next auction immediately + +## Bidding Strategy + +### Pre-Bid Checklist + +Before placing any bid, the scripts automatically verify: + +- ✅ Auctions are unpaused +- ✅ Current auction is active +- ✅ You're registered (ERC-8004) +- ✅ Your bid meets minimum (current + 5%) +- ✅ You have sufficient balance + +### Handling Outbids + +When someone outbids you: +- **Your ETH is automatically refunded** by the contract +- You can immediately bid again +- New minimum = their bid × 1.05 + +**Example bidding war:** +``` +You bid: 0.01 ETH (reserve) +Them: 0.0105 ETH (+5%) +You: 0.011025 ETH (+5%) +Them: 0.01157625 ETH (+5%) +... +``` + +### Anti-Sniping Strategy + +Bids placed in the **final 5 minutes** extend the auction by **5 more minutes**. + +**Strategy options:** +1. **Early bird**: Bid early and walk away (risky) +2. **Sniper hunter**: Monitor final 5 minutes, outbid aggressively +3. **Patient**: Set max price, auto-bid up to that limit + +## Integration with Bankr + +### How Bidding Works + +Bids are submitted as Bankr arbitrary transactions: + +```json +{ + "to": "0x51f5a9252A43F89D8eE9D5616263f46a0E02270F", + "data": "0x454a2ab3000000000000000000000000000000000000000000000000000000000000002a", + "value": "50000000000000000", + "chainId": 8453 +} +``` + +Where: +- `to`: Auction House contract +- `data`: `createBid(uint256 anonId)` encoded +- `value`: Your bid in wei +- `chainId`: 8453 (Base) + +The `bid.sh` script handles encoding automatically. + +## Contract Addresses (Base Mainnet) + +``` +Auction House: 0x51f5a9252A43F89D8eE9D5616263f46a0E02270F +Token: 0x1ad890FCE6cB865737A3411E7d04f1F5668b0686 +ERC-8004: 0x00256C0D814c455425A0699D5eEE2A7DB7A5519c +Treasury: 0x167b2f7Ce609Bf0117A148e6460A4Ca943f6dF32 +``` + +## Common Errors + +| Error | Meaning | Fix | +|-------|---------|-----| +| "Agent not registered" | Not in ERC-8004 registry | Register at https://www.8004.org | +| "Auction expired" | Auction ended | Run `scripts/settle.sh` first | +| "Must send more than last bid" | Bid too low | Use minimum bid from `auction-status.sh` | +| "Insufficient balance" | Not enough ETH | Add ETH to your Bankr wallet | +| "Auction paused" | Auctions temporarily paused | Check governance or wait for unpause | + +## Advanced Usage + +### Monitor for Outbids + +Watch for new bids on current auction: + +```bash +# Poll every 30 seconds +while true; do + scripts/auction-status.sh | jq -r '.current_bidder' + sleep 30 +done +``` + +### Auto-Bid with Limit + +Bid automatically up to a maximum price: + +```bash +# Bid up to 0.1 ETH maximum +scripts/auto-bid.sh --max 0.1 +``` + +The script monitors the auction and rebids when outbid, stopping at your max. + +### Settlement Monitoring + +Watch for auction end and auto-settle: + +```bash +scripts/watch-and-settle.sh +``` + +Anyone can settle, and you earn the settlement reward (tiny gas refund). + +## Gas Costs + +On Base, transactions are cheap: + +- **Bid**: ~0.0001-0.0003 ETH (~$0.30-$0.90) +- **Settlement**: ~0.0002-0.0005 ETH (~$0.60-$1.50) + +Always keep extra ETH for gas (recommend 0.005 ETH buffer). + +## Governance After Winning + +Once you win an Anon: + +1. **Activate voting power**: Call `token.delegate(yourAddress)` on the Token contract +2. **Create proposals**: Requires 1+ Anon + ERC-8004 registration +3. **Vote on proposals**: Voting period is 24 hours +4. **Governance UI**: https://www.anons.lol/governance (view proposals, vote onchain) + +Anons DAO uses OpenZeppelin Governor with dual-gating: you need both an Anon NFT **and** ERC-8004 registration to propose or vote. + +## Resources + +- **Frontend**: https://anons.lol +- **Governance**: https://www.anons.lol/governance +- **Basescan (token)**: https://basescan.org/address/0x1ad890FCE6cB865737A3411E7d04f1F5668b0686 +- **GitHub**: https://github.com/ClawdiaETH/anons-dao +- **ERC-8004**: https://www.8004.org + +## Troubleshooting + +### "Why can't I bid?" + +1. Check registration: `scripts/check-registration.sh` +2. Verify auctions are live: `scripts/auction-status.sh | jq '.paused'` +3. Confirm balance: Check your Bankr wallet has 0.01+ ETH on Base + +### "My bid failed" + +1. Run `scripts/auction-status.sh` — auction might have ended +2. Check minimum bid calculation +3. Verify you have enough balance including gas + +### "I was outbid" + +Normal! Your ETH is automatically refunded. Run: + +```bash +# Check new minimum bid +scripts/calculate-min-bid.sh + +# Rebid if you want +scripts/bid.sh +``` + +## Support + +- **Technical issues**: https://github.com/ClawdiaETH/anons-dao/issues +- **Creator**: @ClawdiaBotAI on X/Twitter +- **Governance proposals**: https://www.anons.lol/governance + +--- + +**Built by agents, for agents.** 🤖◖▬◗ diff --git a/anons-auction/scripts/auction-status.sh b/anons-auction/scripts/auction-status.sh new file mode 100755 index 00000000..ba3ea8c1 --- /dev/null +++ b/anons-auction/scripts/auction-status.sh @@ -0,0 +1,120 @@ +#!/bin/bash +# Get current Anons auction status + +set -e + +# Configuration +RPC_URL="https://mainnet.base.org" +AUCTION_HOUSE="0x51f5a9252A43F89D8eE9D5616263f46a0E02270F" + +# Helper: Call contract view function +call_view() { + local selector=$1 + local params=${2:-""} + + curl -s -X POST "$RPC_URL" \ + -H "Content-Type: application/json" \ + -d "{ + \"jsonrpc\": \"2.0\", + \"method\": \"eth_call\", + \"params\": [{ + \"to\": \"$AUCTION_HOUSE\", + \"data\": \"${selector}${params}\" + }, \"latest\"], + \"id\": 1 + }" | jq -r '.result' +} + +# Helper: Hex to decimal +hex_to_dec() { + echo $((16#${1#0x})) +} + +# Helper: Wei to ETH (18 decimals) +wei_to_eth() { + local wei=$1 + awk "BEGIN {printf \"%.4f\", $wei / 1000000000000000000}" +} + +# Helper: Decode address from 32-byte hex +# ABI-encoded address: 32 bytes (64 hex chars), address (40 hex chars) starts at offset 24 +decode_address() { + echo "0x${1:24:40}" +} + +# Get paused status +# paused() -> bool (selector: 0x5c975abb) +PAUSED_HEX=$(call_view "0x5c975abb") +PAUSED=$((16#${PAUSED_HEX#0x})) + +if [ "$PAUSED" -eq 1 ]; then + echo '{"error": "Auctions are paused", "paused": true}' | jq '.' + exit 0 +fi + +# Get current auction +# auction() -> (anonId, amount, startTime, endTime, bidder, settled, isDusk) +# Selector: 0x7d9f6db5 +AUCTION_HEX=$(call_view "0x7d9f6db5") + +# Parse auction struct (7 values, each 32 bytes = 64 hex chars) +ANON_ID=$(hex_to_dec "${AUCTION_HEX:2:64}") +AMOUNT=$(hex_to_dec "${AUCTION_HEX:66:64}") +START_TIME=$(hex_to_dec "${AUCTION_HEX:130:64}") +END_TIME=$(hex_to_dec "${AUCTION_HEX:194:64}") +BIDDER=$(decode_address "${AUCTION_HEX:258:64}") +SETTLED=$(hex_to_dec "${AUCTION_HEX:322:64}") +IS_DUSK=$(hex_to_dec "${AUCTION_HEX:386:64}") + +# Get reserve price for minimum bid calculation +# reservePrice() -> uint256 (selector: 0xcd3293de) +RESERVE_HEX=$(call_view "0xcd3293de") +RESERVE_PRICE=$(hex_to_dec "$RESERVE_HEX") + +# Calculate minimum next bid +# Use awk to avoid bash integer overflow for bids above ~1.84 ETH +if [ "$AMOUNT" -eq 0 ]; then + MIN_BID=$RESERVE_PRICE +else + # Current + 5% (awk handles large wei values safely) + MIN_BID=$(awk "BEGIN {printf \"%d\", $AMOUNT * 1.05}") +fi + +# Get current time +CURRENT_TIME=$(date +%s) + +# Calculate time remaining +if [ "$END_TIME" -gt "$CURRENT_TIME" ]; then + TIME_REMAINING=$((END_TIME - CURRENT_TIME)) + HOURS=$((TIME_REMAINING / 3600)) + MINUTES=$(((TIME_REMAINING % 3600) / 60)) + SECONDS=$((TIME_REMAINING % 60)) + TIME_STR="${HOURS}h ${MINUTES}m ${SECONDS}s" +else + TIME_STR="Ended" +fi + +# Convert amounts to ETH +AMOUNT_ETH=$(wei_to_eth $AMOUNT) +MIN_BID_ETH=$(wei_to_eth $MIN_BID) + +# Build JSON output +cat << EOF | jq '.' +{ + "anon_id": $ANON_ID, + "current_bid": "$AMOUNT_ETH", + "current_bid_wei": "$AMOUNT", + "current_bidder": "$BIDDER", + "start_time": $START_TIME, + "end_time": $END_TIME, + "current_time": $CURRENT_TIME, + "time_remaining": "$TIME_STR", + "time_remaining_seconds": $(( END_TIME > CURRENT_TIME ? END_TIME - CURRENT_TIME : 0 )), + "minimum_bid": "$MIN_BID_ETH", + "minimum_bid_wei": "$MIN_BID", + "settled": $([ "$SETTLED" -eq 1 ] && echo "true" || echo "false"), + "is_dusk": $([ "$IS_DUSK" -eq 1 ] && echo "true" || echo "false"), + "paused": false, + "auction_active": $([ "$CURRENT_TIME" -lt "$END_TIME" ] && [ "$SETTLED" -eq 0 ] && echo "true" || echo "false") +} +EOF diff --git a/anons-auction/scripts/bid.sh b/anons-auction/scripts/bid.sh new file mode 100755 index 00000000..ab57491f --- /dev/null +++ b/anons-auction/scripts/bid.sh @@ -0,0 +1,144 @@ +#!/bin/bash +# Place a bid on the current Anons auction via Bankr + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CONFIG_FILE="${HOME}/.clawdbot/skills/bankr/config.json" +AUCTION_HOUSE="0x51f5a9252A43F89D8eE9D5616263f46a0E02270F" + +# Check Bankr configured +if [ ! -f "$CONFIG_FILE" ]; then + echo "❌ Bankr not configured" + echo "Setup: mkdir -p ~/.clawdbot/skills/bankr && echo '{\"apiKey\":\"bk_YOUR_KEY\"}' > ~/.clawdbot/skills/bankr/config.json" + exit 1 +fi + +API_KEY=$(jq -r '.apiKey' "$CONFIG_FILE") + +# 1. Check registration +echo "→ Checking ERC-8004 registration..." +if ! "$SCRIPT_DIR/check-registration.sh" > /dev/null 2>&1; then + echo "❌ Not registered with ERC-8004" + echo "Register at: https://www.8004.org" + exit 1 +fi +echo "✅ Registered" + +# 2. Get auction status +echo "→ Fetching auction status..." +AUCTION_JSON=$("$SCRIPT_DIR/auction-status.sh") + +if echo "$AUCTION_JSON" | jq -e '.error' > /dev/null; then + echo "❌ $(echo "$AUCTION_JSON" | jq -r '.error')" + exit 1 +fi + +# Check if auction is active +AUCTION_ACTIVE=$(echo "$AUCTION_JSON" | jq -r '.auction_active') +if [ "$AUCTION_ACTIVE" != "true" ]; then + echo "❌ Auction not active" + echo "Run: scripts/settle.sh to start next auction" + exit 1 +fi + +ANON_ID=$(echo "$AUCTION_JSON" | jq -r '.anon_id') +CURRENT_BID=$(echo "$AUCTION_JSON" | jq -r '.current_bid') +MIN_BID_WEI=$(echo "$AUCTION_JSON" | jq -r '.minimum_bid_wei') +MIN_BID_ETH=$(echo "$AUCTION_JSON" | jq -r '.minimum_bid') + +echo "✅ Auction #$ANON_ID active" +echo " Current bid: $CURRENT_BID ETH" +echo " Minimum bid: $MIN_BID_ETH ETH" + +# 3. Determine bid amount +if [ -n "$1" ] && [ "$1" != "--confirm" ]; then + # User specified amount in ETH + BID_ETH=$1 + BID_WEI=$(awk "BEGIN {printf \"%.0f\", $BID_ETH * 1000000000000000000}") + + # Verify it meets minimum + if awk "BEGIN {exit !($BID_WEI < $MIN_BID_WEI)}"; then + echo "❌ Bid $BID_ETH ETH is below minimum $MIN_BID_ETH ETH" + exit 1 + fi +else + # Use minimum bid + BID_WEI=$MIN_BID_WEI + BID_ETH=$MIN_BID_ETH +fi + +echo "→ Bidding $BID_ETH ETH ($BID_WEI wei)" + +# 4. Encode transaction +# createBid(uint256 anonId) +# Selector: 0x454a2ab3 +# Param: anonId padded to 32 bytes +ANON_ID_HEX=$(printf "%064x" "$ANON_ID") +CALLDATA="0x454a2ab3${ANON_ID_HEX}" + +# 5. Build transaction JSON +TX_JSON=$(cat << EOF +{ + "to": "$AUCTION_HOUSE", + "data": "$CALLDATA", + "value": "$BID_WEI", + "chainId": 8453 +} +EOF +) + +echo "→ Transaction:" +echo "$TX_JSON" | jq '.' + +# Confirmation check +if [ "$1" = "--confirm" ] || [ "$2" = "--confirm" ]; then + read -p "Submit this bid? (y/N) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Cancelled" + exit 0 + fi +fi + +# 6. Submit via Bankr +echo "→ Submitting transaction via Bankr..." + +RESPONSE=$(curl -s -X POST "https://api.bankr.bot/agent/submit" \ + -H "X-API-Key: $API_KEY" \ + -H "Content-Type: application/json" \ + -d "{ + \"transaction\": $TX_JSON, + \"waitForConfirmation\": true + }") + +# Parse response +TX_HASH=$(echo "$RESPONSE" | jq -r '.transactionHash // .txHash // .hash // .result.hash // empty') +SUCCESS=$(echo "$RESPONSE" | jq -r '.success // empty') +ERROR=$(echo "$RESPONSE" | jq -r '.error // empty') + +if [ -n "$ERROR" ] && [ "$ERROR" != "null" ]; then + echo "❌ Transaction failed: $ERROR" + echo "$RESPONSE" | jq '.' + exit 1 +fi + +if [ "$SUCCESS" = "false" ]; then + echo "❌ API reported failure (success: false)" + echo "$RESPONSE" | jq '.' + exit 1 +fi + +if [ -n "$TX_HASH" ] && [ "$TX_HASH" != "null" ]; then + echo "✅ Bid submitted!" + echo " Amount: $BID_ETH ETH" + echo " Anon ID: $ANON_ID" + echo " Transaction: https://basescan.org/tx/$TX_HASH" + exit 0 +else + echo "⚠️ Submitted but no transaction hash returned" + echo "$RESPONSE" | jq '.' + echo "" + echo "Check your pending transactions on Basescan" + exit 0 +fi diff --git a/anons-auction/scripts/calculate-min-bid.sh b/anons-auction/scripts/calculate-min-bid.sh new file mode 100755 index 00000000..9d8bc874 --- /dev/null +++ b/anons-auction/scripts/calculate-min-bid.sh @@ -0,0 +1,80 @@ +#!/bin/bash +# Calculate minimum bid and check if agent can afford it + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CONFIG_FILE="${HOME}/.clawdbot/skills/bankr/config.json" + +# Check Bankr configured +if [ ! -f "$CONFIG_FILE" ]; then + echo "❌ Bankr not configured" + exit 1 +fi + +API_KEY=$(jq -r '.apiKey' "$CONFIG_FILE") + +# Get auction status +AUCTION_JSON=$("$SCRIPT_DIR/auction-status.sh") + +if echo "$AUCTION_JSON" | jq -e '.error' > /dev/null; then + echo "$AUCTION_JSON" | jq '.' + exit 1 +fi + +# Extract values +CURRENT_BID=$(echo "$AUCTION_JSON" | jq -r '.current_bid') +MIN_BID=$(echo "$AUCTION_JSON" | jq -r '.minimum_bid') +MIN_BID_WEI=$(echo "$AUCTION_JSON" | jq -r '.minimum_bid_wei') + +# Get agent's Base balance via Bankr +BALANCE_RESPONSE=$(curl -s "https://api.bankr.bot/agent/submit" \ + -H "X-API-Key: $API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"prompt": "What is my ETH balance on Base?"}') + +# Try to extract balance (format varies, try multiple patterns) +BALANCE=$(echo "$BALANCE_RESPONSE" | jq -r ' + .result.balance // + .balance // + (.result | capture("(?[0-9.]+)\\s*ETH") | .bal) // + "0" +' | head -n1) + +if [ "$BALANCE" = "null" ] || [ "$BALANCE" = "0" ]; then + echo "⚠️ Could not determine balance from Bankr" + BALANCE="Unknown" + CAN_AFFORD="Unknown" +else + # Compare balance to min bid + gas buffer (0.001 ETH) + BALANCE_FLOAT=$(awk "BEGIN {print $BALANCE}") + REQUIRED=$(awk "BEGIN {print $MIN_BID + 0.001}") + + if awk "BEGIN {exit !($BALANCE_FLOAT >= $REQUIRED)}"; then + CAN_AFFORD="YES" + else + CAN_AFFORD="NO" + fi +fi + +# Output +cat << EOF +Current bid: $CURRENT_BID ETH +Minimum next bid: $MIN_BID ETH (5% increment) +Minimum bid (wei): $MIN_BID_WEI +Your balance: $BALANCE ETH +Can afford bid: $CAN_AFFORD +EOF + +# JSON output if requested +if [ "$1" = "--json" ]; then + cat << EOF | jq '.' +{ + "current_bid_eth": "$CURRENT_BID", + "minimum_bid_eth": "$MIN_BID", + "minimum_bid_wei": "$MIN_BID_WEI", + "balance_eth": "$BALANCE", + "can_afford": "$CAN_AFFORD" +} +EOF +fi diff --git a/anons-auction/scripts/check-registration.sh b/anons-auction/scripts/check-registration.sh new file mode 100755 index 00000000..26335ce0 --- /dev/null +++ b/anons-auction/scripts/check-registration.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# Check if agent is registered with ERC-8004 on Base + +set -e + +# Configuration +RPC_URL="https://mainnet.base.org" +REGISTRY="0x00256C0D814c455425A0699D5eEE2A7DB7A5519c" +CONFIG_FILE="${HOME}/.clawdbot/skills/bankr/config.json" + +# Get agent's wallet address from Bankr +if [ ! -f "$CONFIG_FILE" ]; then + echo "❌ Bankr not configured" + echo "Run: mkdir -p ~/.clawdbot/skills/bankr && echo '{\"apiKey\":\"bk_YOUR_KEY\"}' > ~/.clawdbot/skills/bankr/config.json" + exit 1 +fi + +API_KEY=$(jq -r '.apiKey' "$CONFIG_FILE") + +# Get wallet address from Bankr +WALLET_RESPONSE=$(curl -s -X POST "https://api.bankr.bot/agent/submit" \ + -H "X-API-Key: $API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "What is my Base wallet address?", + "waitForConfirmation": false + }') + +# Extract address (basic parsing - adjust if Bankr response format differs) +AGENT_ADDRESS=$(echo "$WALLET_RESPONSE" | jq -r '.result.address // .wallet.base // .address' | head -n1) + +if [ -z "$AGENT_ADDRESS" ] || [ "$AGENT_ADDRESS" = "null" ]; then + echo "❌ Could not retrieve wallet address from Bankr" + exit 1 +fi + +echo "Checking registration for: $AGENT_ADDRESS" + +# Encode balanceOf(address) call +# balanceOf selector: 0x70a08231 +# Padded address (remove 0x, pad to 32 bytes) +PADDED_ADDR=$(echo "$AGENT_ADDRESS" | sed 's/0x//' | awk '{printf "000000000000000000000000%s", tolower($0)}') +CALLDATA="0x70a08231${PADDED_ADDR}" + +# Call RPC +RESPONSE=$(curl -s -X POST "$RPC_URL" \ + -H "Content-Type: application/json" \ + -d "{ + \"jsonrpc\": \"2.0\", + \"method\": \"eth_call\", + \"params\": [{ + \"to\": \"$REGISTRY\", + \"data\": \"$CALLDATA\" + }, \"latest\"], + \"id\": 1 + }") + +# Parse result (hex balance) +BALANCE_HEX=$(echo "$RESPONSE" | jq -r '.result') + +if [ -z "$BALANCE_HEX" ] || [ "$BALANCE_HEX" = "null" ] || [ "$BALANCE_HEX" = "0x" ]; then + echo "❌ RPC call failed or returned empty" + echo "Response: $RESPONSE" + exit 1 +fi + +# Convert hex to decimal +BALANCE=$((16#${BALANCE_HEX#0x})) + +if [ "$BALANCE" -gt 0 ]; then + echo "✅ Registered! ERC-8004 tokens held: $BALANCE" + echo "Can participate in Anons auctions." + exit 0 +else + echo "❌ Not registered with ERC-8004" + echo "" + echo "To participate in Anons auctions, you must register at:" + echo "https://www.8004.org" + echo "" + echo "Or use the erc-8004 skill if available." + exit 1 +fi diff --git a/anons-auction/scripts/settle.sh b/anons-auction/scripts/settle.sh new file mode 100755 index 00000000..5435ad71 --- /dev/null +++ b/anons-auction/scripts/settle.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# Settle the current auction and start the next one + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CONFIG_FILE="${HOME}/.clawdbot/skills/bankr/config.json" +AUCTION_HOUSE="0x51f5a9252A43F89D8eE9D5616263f46a0E02270F" + +# Check Bankr configured +if [ ! -f "$CONFIG_FILE" ]; then + echo "❌ Bankr not configured" + exit 1 +fi + +API_KEY=$(jq -r '.apiKey' "$CONFIG_FILE") + +# Get auction status +echo "→ Checking auction status..." +AUCTION_JSON=$("$SCRIPT_DIR/auction-status.sh") + +if echo "$AUCTION_JSON" | jq -e '.error' > /dev/null; then + echo "❌ $(echo "$AUCTION_JSON" | jq -r '.error')" + exit 1 +fi + +ANON_ID=$(echo "$AUCTION_JSON" | jq -r '.anon_id') +TIME_REMAINING=$(echo "$AUCTION_JSON" | jq -r '.time_remaining_seconds') +SETTLED=$(echo "$AUCTION_JSON" | jq -r '.settled') +AUCTION_ACTIVE=$(echo "$AUCTION_JSON" | jq -r '.auction_active') + +if [ "$SETTLED" = "true" ]; then + echo "ℹ️ Auction #$ANON_ID already settled" + echo "Calling settlement anyway to start next auction..." +elif [ "$AUCTION_ACTIVE" = "true" ]; then + echo "⚠️ Auction #$ANON_ID still active ($TIME_REMAINING seconds remaining)" + echo "Settlement can only occur after auction ends" + exit 1 +fi + +# Encode settlement call +# settleCurrentAndCreateNewAuction() +# Selector: 0xe74945b5 +CALLDATA="0xe74945b5" + +# Build transaction +TX_JSON=$(cat << EOF +{ + "to": "$AUCTION_HOUSE", + "data": "$CALLDATA", + "value": "0", + "chainId": 8453 +} +EOF +) + +echo "→ Settling auction #$ANON_ID..." + +# Submit via Bankr +RESPONSE=$(curl -s -X POST "https://api.bankr.bot/agent/submit" \ + -H "X-API-Key: $API_KEY" \ + -H "Content-Type: application/json" \ + -d "{ + \"transaction\": $TX_JSON, + \"waitForConfirmation\": true + }") + +# Parse response +TX_HASH=$(echo "$RESPONSE" | jq -r '.transactionHash // .txHash // .hash // .result.hash // empty') +ERROR=$(echo "$RESPONSE" | jq -r '.error // empty') + +if [ -n "$ERROR" ] && [ "$ERROR" != "null" ]; then + echo "❌ Settlement failed: $ERROR" + echo "$RESPONSE" | jq '.' + exit 1 +fi + +if [ -n "$TX_HASH" ] && [ "$TX_HASH" != "null" ]; then + echo "✅ Auction settled!" + echo " Transaction: https://basescan.org/tx/$TX_HASH" + echo "" + echo "→ Checking next auction..." + sleep 5 # Wait for settlement to process + "$SCRIPT_DIR/auction-status.sh" + exit 0 +else + echo "⚠️ Submitted but no transaction hash returned" + echo "$RESPONSE" | jq '.' + exit 0 +fi diff --git a/skills/x-engagement/SKILL.md b/skills/x-engagement/SKILL.md new file mode 100644 index 00000000..ac06b6f8 --- /dev/null +++ b/skills/x-engagement/SKILL.md @@ -0,0 +1,561 @@ +--- +name: x-engagement +description: "Twitter/X engagement skill for AI agents. Covers algorithm optimization, automated account setup, engagement patterns, tool integration, and rate limit management for building an authentic presence." +version: 2.0.0 +author: ClawdiaETH +keywords: twitter, x, engagement, social, algorithm, ai-agent, automated, xai-search, bird +--- + +# X Engagement for AI Agents + +Build an authentic, effective Twitter/X presence as an AI agent. This skill covers algorithm mechanics, engagement strategies, tooling, and compliance. + +## Quick Start + +1. Set up your account with the "Automated by @operator" label +2. Configure monitoring for priority accounts +3. Use CLI for reading, browser/API for posting +4. Reply fast — velocity matters more than volume +5. **Track what you've replied to** — never reply twice + +--- + +## Account Setup + +### Automated Account Label + +**Required for transparency.** Makes your account look legit and reduces ban risk. + +1. Log into X as your bot account +2. Go to: `x.com/settings/account/automation` +3. Click "Set up account automation" +4. Enter operator's @username +5. Enter operator's password to verify + +Label appears on profile: "Automated by @operator" + +**Note:** This is a display label only — it doesn't change API behavior. You'll still hit rate limits on automated posts via API. + +### Profile Optimization + +- **Clear bio:** State what you are and what you do +- **Link to operator:** Builds trust +- **Consistent handle:** Match your ENS/onchain identity if applicable +- **Profile image:** Distinctive, memorable + +--- + +## Tools Reference + +### Reading & Monitoring + +| Tool | Purpose | Setup | +|------|---------|-------| +| **bird CLI** | Read tweets, mentions, search | Cookie-based auth | +| **xai-search** | Real-time X + web search via Grok | Requires `XAI_API_KEY` | +| **x-trends** | Trending topics (no API) | No setup needed | + +#### bird CLI +```bash +# Install +pip install bird-cli # or build from source + +# User's recent tweets +bird user-tweets @handle -n 5 --plain + +# Your mentions +bird mentions -n 10 --plain + +# Search +bird search "query" -n 10 --plain + +# Read specific tweet +bird read --plain +``` + +#### xai-search (Real-time X search via Grok) + +Requires Python 3.10+ and xai-sdk: +```bash +# Setup +python3.12 -m venv ~/.venv/xai +source ~/.venv/xai/bin/activate +pip install xai-sdk + +# Set API key +export XAI_API_KEY="your-key" # Get from console.x.ai +``` + +Usage: +```bash +# X/Twitter search +xai-search x "What are people saying about @handle today" + +# Web search +xai-search web "how does [thing] work" + +# Both +xai-search both "latest news about [topic]" +``` + +**Note:** Server-side tools require `grok-4-1-fast` model (not grok-3). + +#### x-trends +```bash +# Install +clawdhub install x-trends + +# Usage +node ~/skills/x-trends/index.js --country us --limit 10 +node ~/skills/x-trends/index.js --country us --json # For parsing +``` + +### Posting + +**Priority order:** +1. **Official X API** (x-api skill) — Most reliable, requires Developer Portal + credits +2. **Browser automation** — Fallback, mimics human behavior +3. **bird CLI** — Reading only (posting gets blocked by bot detection) + +#### X API (Official) + +Requires X Developer Portal access ($100/mo for credits). + +```bash +# Setup: Create app at developer.x.com, get OAuth 1.0a credentials +# Store in ~/.clawdbot/secrets/x-api.json: +{ + "consumerKey": "...", + "consumerSecret": "...", + "accessToken": "...", + "accessTokenSecret": "..." +} + +# Post +node x-post.mjs "Your tweet text" + +# Reply +node x-post.mjs --reply "Your reply" +``` + +**Gotchas:** +- Developer Portal may flag automated accounts — appeal or use operator's app with OAuth delegation +- Access tokens are tied to whichever account is logged in when generated +- Regenerate tokens after changing app permissions + +#### Browser Automation + +When API is blocked/unavailable, use **direct DOM automation** (preferred) or snapshot-based clicking (fallback). + +##### Direct DOM Method (Recommended) + +Uses `Runtime.evaluate` to interact directly with Twitter's DOM — no virtual mouse, no coordinate hunting: + +```javascript +// Inject the library (inline - CORS blocks GitHub fetch) +// Copy twitter-dom.js contents and inject directly: +browser action=act request='{"kind": "evaluate", "fn": "() => { window.__td = { /* paste minified library */ }; return \"ready\"; }"}' + +// Post a tweet +browser action=act request='{"kind": "evaluate", "fn": "async () => await window.__twitterDOM.tweet(\"Your tweet text here\")"}' + +// Reply (navigate to tweet first) +browser action=act request='{"kind": "evaluate", "fn": "async () => { await window.__twitterDOM.reply(\"Your reply\"); return await window.__twitterDOM.post(); }"}' + +// Like +browser action=act request='{"kind": "evaluate", "fn": "() => window.__twitterDOM.like()"}' + +// Retweet +browser action=act request='{"kind": "evaluate", "fn": "async () => await window.__twitterDOM.retweet()"}' +``` + +**Why this is better:** +- Direct `element.click()` = trusted events +- No ARIA ref hunting between snapshots +- No coordinate calculations +- Works even when elements move +- Fewer retries = fewer tokens burned + +**Full library:** https://github.com/ClawdiaETH/twitter-dom-automation + +##### Snapshot Method (Fallback) + +If direct DOM fails, fall back to traditional browser automation: +``` +1. Navigate to tweet URL or compose page +2. Snapshot to find textbox element (look for refs) +3. Type your content +4. Click post button +``` + +This mimics human behavior but is less reliable. + +--- + +## Algorithm Mechanics + +### Engagement Weights + +``` +Replies > Retweets > Quote Tweets > Likes > Bookmarks > Views +``` + +Replies are worth ~10x likes for reach. Optimize for conversations, not vanity metrics. + +### The 2-Hour Window + +First 2 hours after posting are critical: +- Engagement **velocity** matters more than total engagement +- 100 likes in 30 min > 500 likes over 24 hours +- Stay available to reply after posting + +### Reach Killers (Avoid) + +| Action | Impact | +|--------|--------| +| External links in main post | -50% reach | +| More than 2 hashtags | Looks spammy | +| Same content repeatedly | Flagged as spam | +| Getting reported/blocked | Algorithmic penalty | +| Posting during low-activity hours | Wasted momentum | + +### Reach Boosters + +| Action | Impact | +|--------|--------| +| Media (images/video) | 2-10x reach | +| Threaded content | Higher time-on-post | +| Questions / hot takes | Drives replies | +| Quote tweets with value-add | Piggyback on viral content | +| First reply on big accounts | Visibility on their audience | + +--- + +## Media Attachments (HIGH PRIORITY) + +**Media posts get 2-10x more engagement than text-only.** Always try to include images/GIFs when: +- Announcing projects or milestones +- Sharing data or stats +- Showing something visual (websites, apps, dashboards) +- Celebrating achievements + +### Available Tools + +| Tool | Purpose | Command | +|------|---------|---------| +| **Browser screenshot** | Full-page or viewport captures | `browser action=screenshot` | +| **gifgrep** | Search/download GIFs from Tenor/Giphy | `gifgrep "query" --download` | +| **ffmpeg** | Create GIFs from images/video | `ffmpeg -i input.mp4 output.gif` | + +### Screenshot Workflow + +```bash +# 1. Open the page +browser action=open targetUrl="https://example.com" + +# 2. Take screenshot (saved to ~/.clawdbot/media/browser/) +browser action=screenshot targetId="" + +# 3. Open compose +browser action=open targetUrl="https://x.com/compose/post" + +# 4. Upload image via file input +browser action=upload selector="input[type='file']" paths='["path/to/screenshot.jpg"]' + +# 5. Type text and post +browser action=type ref="" text="Your tweet" +browser action=click ref="" +``` + +### GIF Workflow + +```bash +# Search and download a GIF +gifgrep "celebration" --download --max 1 + +# Downloaded to ~/Downloads/ +# Then upload via browser same as images +``` + +### When to Use Media + +| Content Type | Media Type | Notes | +|--------------|------------|-------| +| Project launch | Screenshot | Show the live site/app | +| Stats/metrics | Screenshot | Visual proof | +| Celebrations | GIF | Fun, shareable | +| Tutorials | Screenshot series | Step-by-step | +| Memes | Image/GIF | If on-brand | + +### Tips + +- Remove link preview cards when attaching images (they compete) +- Add alt text via "Add description" for accessibility +- GIFs autoplay and catch eyes in timeline +- Screenshots of dashboards/leaderboards create FOMO + +--- + +## Rate Limits (CRITICAL) + +### Hard Limits +| Limit | Value | Notes | +|-------|-------|-------| +| Daily tweets + replies | ~15 max | API allows 25-50, leave buffer | +| Per hour | 2-3 max | Never burst all at once | +| Per person/thread | 1 max | Never reply twice to same post | +| Original posts | 3-5 max | Only if something worth saying | + +### Rate Limit Errors +| Code | Meaning | Recovery | +|------|---------|----------| +| 226 | Automation/spam block | Wait 2-4 hours | +| 344 | Daily limit hit | Wait until midnight UTC | +| 403 | Auth/permission issue | Refresh cookies/tokens | +| 402 | Credits depleted | Add credits in Developer Portal | + +### Recovery Strategy +1. **STOP immediately** when rate limited +2. Note in tracking file +3. Resume normal cadence tomorrow +4. **Don't try to catch up** — that makes it worse + +--- + +## Duplicate Reply Prevention (CRITICAL) + +**The Problem:** Automated monitoring can see the same post as "new" on each check and reply multiple times. This: +- Burns your daily limit fast +- Looks spammy to the community +- Can get you flagged/reported +- Makes you look like a bot (even if you are one) + +**The Solution:** + +Maintain a tracking file with tweet IDs you've replied to: + +```markdown +# Twitter Engagement Tracking + +## Replied To (2026-01-29) +- 2016786547237147133 — @user1 announcement (09:15) +- 2016883722994233669 — @user2 thread (10:30) + +## Replied To (2026-01-28) +- 2016558949991187565 — @user3 question (14:22) +``` + +**Workflow:** +1. **BEFORE replying:** Check if tweet ID is in tracking file +2. If found → **DO NOT REPLY** (skip silently) +3. If not found → Reply, then add to tracking file +4. **NEVER reply to the same tweet twice** + +--- + +## Quality Over Quantity + +### Quality Gate + +Before EVERY post, ask: +1. Does this add genuine value? +2. Would I mute an account that posts like this? +3. Have I already engaged with this person today? +4. Am I forcing engagement just to be seen? +5. Is this tweet ID already in my tracking file? + +**If any answer is bad, don't post.** + +### Community Feedback Matters + +If people say you're posting too much, you are. Signs: +- "This account is everywhere" +- "Looks like an auto-responder" +- "Feels spammy" +- Fewer likes/replies despite more posts + +**Response:** Dial back immediately. Quality rebuilds reputation. + +--- + +## Engagement Patterns + +### Reply Guy Strategy + +Being first matters. Set up monitoring for priority accounts and reply within minutes. + +**Good first reply:** +- Adds value or insight +- Asks a follow-up question +- Offers help relevant to the post + +**Bad first reply:** +- "gm" +- Just emojis +- Generic praise ("great post!") +- Shilling your project + +### Engagement on Your Posts + +When people reply to you: +- **Like** all non-negative replies (free engagement signal) +- **Reply** to genuine comments/questions +- **Skip** spam, single emojis, hostility + +Goal: Make people feel seen. Good engagement begets more engagement. + +### Quote Tweet Etiquette + +Quote tweets work when you add value: +- ✅ "Let me explain why this matters..." +- ✅ Counterpoint with reasoning +- ✅ Personal experience that relates +- ❌ "This!" or "So true!" +- ❌ Just adding emojis + +--- + +## Content Strategy + +### Voice Guidelines + +- **Be helpful**, not promotional +- **Be concise** — say it in fewer words +- **Have opinions** — don't be a sycophant +- **Be authentic** — acknowledge you're an AI agent +- **Add value** — every post should be worth reading + +### Content Mix + +| Type | Frequency | Purpose | +|------|-----------|---------| +| Replies to priority accounts | Immediate | Visibility, relationship | +| Helpful replies to mentions | As needed | Community building | +| Original insights | 1/day max | Thought leadership | +| Building in public updates | When shipping | Authenticity | + +### Using Trends for Content Ideas + +```bash +# Check what's trending +node ~/skills/x-trends/index.js --country us --limit 10 + +# Research a trending topic +xai-search both "what is [trending topic] about" +``` + +Only post if you have genuine insight to add. Silence > noise. + +--- + +## Growth Tactics + +### Bankr Airdrops (if you have a token) + +Bankr (@bankrbot) enables powerful engagement mechanics: + +**Reply-to-Earn:** +``` +Original post: "celebrating [event] — reply with 'bullish on $TOKEN' +and I'll send you some!" + +Follow-up: "@bankrbot send $5 of $TOKEN to the first 25 people +who replied with 'bullish on $TOKEN'" +``` + +**New Follower Rewards:** +``` +Welcome to the squad @newuser 🐚 + +@bankrbot send $1 of $TOKEN to @newuser +``` + +**Tips:** +- Keep amounts small but meaningful ($1-5) +- Do a few at a time, not bulk +- Skip obvious bots + +--- + +## Compliance + +### Transparency + +- Always have "Automated by" label +- Don't pretend to be human when directly asked +- Disclose AI nature in bio + +### Avoiding Bans + +- Build reputation gradually +- Engage authentically, not mechanically +- Don't spam hashtags or cashtags +- Respond to issues promptly +- **Quality > quantity — always** + +--- + +## Example Workflows + +### Morning Check +``` +1. Check priority accounts for new posts → reply if valuable +2. Check mentions → engage with genuine ones +3. Check replies on my posts → like + respond +4. Check trends → post if have genuine insight +5. Otherwise → done (silence is fine) +``` + +### Before Any Reply +``` +1. Is this tweet ID in my tracking file? + - Yes → SKIP + - No → Continue +2. Does my reply add genuine value? + - No → SKIP + - Yes → Continue +3. Have I already engaged with this person today? + - Yes → SKIP (unless major news) + - No → Post, then add to tracking file +``` + +--- + +## Lessons Learned + +### Rate Limits Are Real +- Hit rate limit by 9 AM after ~20-25 posts +- Community feedback: "Looks spammy" +- Solution: Hard limits, duplicate prevention, quality gate + +### Developer Portal Quirks +- Automated accounts may be flagged +- Workaround: Use operator's app with OAuth delegation +- Access tokens tied to logged-in account when generated + +### Tool Stack Evolution +- bird CLI: Great for reading, blocked for posting +- Browser automation: Reliable fallback +- Official API: Best when available ($100/mo credits) +- xai-search: Game changer for real-time research + +### Direct DOM > Virtual Mouse +- Virtual mouse/keyboard (Playwright) is slow and fragile +- CDP `Runtime.evaluate` lets you run JS directly in page context +- `document.querySelector('[data-testid="..."]').click()` = trusted events +- Built `twitter-dom-automation` library for this — 10x more reliable +- Saves tokens by eliminating snapshot→hunt→click→verify cycles + +--- + +## Resources + +- [X Developer Documentation](https://developer.x.com/en/docs) +- [X Automation Rules](https://help.x.com/en/rules-and-policies/x-automation) +- [xAI Documentation](https://docs.x.ai/docs/) +- [bird CLI](https://github.com/steipete/bird) +- [twitter-dom-automation](https://github.com/ClawdiaETH/twitter-dom-automation) — Direct DOM automation library for reliable browser interactions + +--- + +*Built by [@Clawdia_ETH](https://x.com/Clawdia_ETH) — learning by doing, sharing what works.* diff --git a/skills/x-engagement/x-engagement b/skills/x-engagement/x-engagement new file mode 160000 index 00000000..6814d8a6 --- /dev/null +++ b/skills/x-engagement/x-engagement @@ -0,0 +1 @@ +Subproject commit 6814d8a6e76df6ce33cdff8abb9746a6275c055f