Back to skills
SkillHub ClubAnalyze Data & AIFull StackData / AI

pet-operator

Delegate Aavegotchi petting rights to AAI's wallet on Base. Generate approve/revoke tx data, check approval, and maintain delegated wallet bookkeeping in pet-me-master config.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
3,129
Hot score
99
Updated
March 20, 2026
Overall rating
C4.0
Composite score
4.0
Best-practice grade
B70.7

Install command

npx @skill-hub/cli install openclaw-skills-pet-operator

Repository

openclaw/skills

Skill path: skills/aaigotchi/pet-operator

Delegate Aavegotchi petting rights to AAI's wallet on Base. Generate approve/revoke tx data, check approval, and maintain delegated wallet bookkeeping in pet-me-master config.

Open repository

Best for

Primary workflow: Analyze Data & AI.

Technical facets: Full Stack, Data / AI.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: openclaw.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install pet-operator into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/openclaw/skills before adding pet-operator to shared team environments
  • Use pet-operator for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: pet-operator
description: Delegate Aavegotchi petting rights to AAI's wallet on Base. Generate approve/revoke tx data, check approval, and maintain delegated wallet bookkeeping in pet-me-master config.
metadata:
  openclaw:
    requires:
      bins:
        - cast
        - jq
---

# pet-operator

Set or revoke AAI as pet operator for user wallets, and keep delegation bookkeeping aligned.

## Constants

- AAI operator wallet: `0xb96B48a6B190A9d509cE9312654F34E9770F2110`
- Aavegotchi Diamond: `0xA99c4B08201F2913Db8D28e71d020c4298F29dBF`
- Chain: Base mainnet (`8453`)
- RPC default: `https://mainnet.base.org`

Overridable env:
- `AAVEGOTCHI_DIAMOND`
- `AAI_OPERATOR`
- `BASE_RPC_URL`
- `PET_ME_CONFIG_FILE`

## Scripts

- `./scripts/check-approval.sh <wallet>`
  - Checks `isPetOperatorForAll(owner, operator)`.
- `./scripts/generate-delegation-tx.sh <wallet>`
  - Generates call data for `setPetOperatorForAll(AAI_OPERATOR, true)`.
- `./scripts/generate-revoke-tx.sh <wallet>`
  - Generates call data for `setPetOperatorForAll(AAI_OPERATOR, false)`.
- `./scripts/add-delegated-wallet.sh <wallet> [name]`
  - Verifies approval, fetches owned gotchi IDs, upserts into `pet-me-master` config.
- `./scripts/remove-delegated-wallet.sh <wallet>`
  - Removes wallet bookkeeping entries from config.

## Config Bookkeeping

`add-delegated-wallet.sh` writes to:
- `.delegatedWallets` (preferred)
- `.wallets` (legacy compatibility, only if present)

This does not grant on-chain permissions by itself; on-chain approval must already exist.

## Security

- Operator permission only enables petting, not transfer.
- User keeps full ownership.
- Revocation is one on-chain tx away.


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### scripts/check-approval.sh

```bash
#!/usr/bin/env bash
# Check if a wallet has approved AAI as pet operator

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "$SCRIPT_DIR/lib.sh"

usage() {
  echo "Usage: $0 <WALLET_ADDRESS>"
  exit 1
}

[[ $# -eq 1 ]] || usage
WALLET="$(normalize_wallet "$1")"

require_read_tools

if check_pet_operator_approved "$WALLET"; then
  echo "approved"
  exit 0
fi

echo "not_approved"
exit 1

```

### scripts/generate-delegation-tx.sh

```bash
#!/usr/bin/env bash
# Generate pet operator delegation transaction details (approved=true)

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "$SCRIPT_DIR/lib.sh"

usage() {
  echo "Usage: $0 <WALLET_ADDRESS>"
  exit 1
}

[[ $# -eq 1 ]] || usage
WALLET="$(normalize_wallet "$1")"

DATA="$(set_pet_operator_calldata true)"

cat <<OUT
πŸ”‘ Pet Operator Delegation
==========================

Wallet: $WALLET
Operator: $AAI_OPERATOR (AAI)

Transaction Details:
====================
To: $AAVEGOTCHI_DIAMOND
Amount: 0 ETH
Network: Base (8453)
RPC: $BASE_RPC_URL

Hex Data:
$DATA

What this does: approves AAI to pet your gotchis (you keep ownership).
OUT

```

### scripts/generate-revoke-tx.sh

```bash
#!/usr/bin/env bash
# Generate transaction to revoke pet operator approval (approved=false)

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "$SCRIPT_DIR/lib.sh"

usage() {
  echo "Usage: $0 <WALLET_ADDRESS>"
  exit 1
}

[[ $# -eq 1 ]] || usage
WALLET="$(normalize_wallet "$1")"

DATA="$(set_pet_operator_calldata false)"

cat <<OUT
πŸ”“ Revoke Pet Operator Delegation
=================================

Wallet: $WALLET
Revoking operator: $AAI_OPERATOR (AAI)

Transaction Details:
====================
To: $AAVEGOTCHI_DIAMOND
Amount: 0 ETH
Network: Base (8453)
RPC: $BASE_RPC_URL

Hex Data (approved=false):
$DATA

What this does: removes AAI's ability to pet your gotchis.
OUT

```

### scripts/add-delegated-wallet.sh

```bash
#!/usr/bin/env bash
# Add a delegated wallet record to pet-me-master config

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "$SCRIPT_DIR/lib.sh"

usage() {
  echo "Usage: $0 <WALLET_ADDRESS> [NAME]"
  exit 1
}

[[ $# -ge 1 ]] || usage
WALLET="$(normalize_wallet "$1")"
NAME="${2:-Delegated Wallet}"

require_read_tools

echo "πŸ“‹ Add Delegated Wallet"
echo "======================="
echo "Wallet: $WALLET"

echo "Checking pet operator approval..."
if ! check_pet_operator_approved "$WALLET"; then
  err "Wallet $WALLET has not approved AAI as pet operator. Run generate-delegation-tx.sh first."
fi
echo "βœ… Wallet approved"

echo "Fetching owned gotchi IDs..."
mapfile -t GOTCHI_IDS < <(fetch_wallet_gotchi_ids "$WALLET")
COUNT="${#GOTCHI_IDS[@]}"

if [ "$COUNT" -eq 0 ]; then
  IDS_JSON='[]'
else
  IDS_JSON="$(printf '%s\n' "${GOTCHI_IDS[@]}" | jq -R . | jq -s '.')"
fi

echo "Found $COUNT gotchi(s)"
if [ "$COUNT" -gt 0 ]; then
  printf 'IDs: %s\n' "$(IFS=,; echo "${GOTCHI_IDS[*]}")"
fi

CONFIG_FILE="$PET_ME_CONFIG_FILE"
[ -f "$CONFIG_FILE" ] || err "Pet-me-master config not found: $CONFIG_FILE"

TS="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
ADDR_LC="$(to_lower "$WALLET")"

cp -f "$CONFIG_FILE" "${CONFIG_FILE}.bak.$(date +%Y%m%d-%H%M%S)"

jq \
  --arg name "$NAME" \
  --arg addr "$WALLET" \
  --arg addr_lc "$ADDR_LC" \
  --arg ts "$TS" \
  --argjson ids "$IDS_JSON" \
  '
  .delegatedWallets = ((.delegatedWallets // [])
    | map(select(((.address // "") | ascii_downcase) != $addr_lc))
    + [{name:$name,address:$addr,gotchiIds:$ids,approved:true,updatedAt:$ts}])
  | if has("wallets") then
      .wallets = ((.wallets // [])
        | map(select(((.address // "") | ascii_downcase) != $addr_lc))
        + [{name:$name,address:$addr,gotchiIds:$ids}])
    else
      .
    end
  ' "$CONFIG_FILE" > "${CONFIG_FILE}.tmp"

mv "${CONFIG_FILE}.tmp" "$CONFIG_FILE"

echo "βœ… Delegated wallet saved"
echo "Config: $CONFIG_FILE"
echo "delegatedWallets count: $(jq '.delegatedWallets | length' "$CONFIG_FILE")"

```

### scripts/remove-delegated-wallet.sh

```bash
#!/usr/bin/env bash
# Remove a delegated wallet record from pet-me-master config

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "$SCRIPT_DIR/lib.sh"

usage() {
  echo "Usage: $0 <WALLET_ADDRESS>"
  exit 1
}

[[ $# -eq 1 ]] || usage
WALLET="$(normalize_wallet "$1")"
ADDR_LC="$(to_lower "$WALLET")"

CONFIG_FILE="$PET_ME_CONFIG_FILE"
[ -f "$CONFIG_FILE" ] || err "Pet-me-master config not found: $CONFIG_FILE"

BEFORE_DELEGATED="$(jq --arg addr_lc "$ADDR_LC" '[.delegatedWallets[]? | select(((.address // "") | ascii_downcase) == $addr_lc)] | length' "$CONFIG_FILE")"
BEFORE_WALLETS="$(jq --arg addr_lc "$ADDR_LC" '[.wallets[]? | select(((.address // "") | ascii_downcase) == $addr_lc)] | length' "$CONFIG_FILE")"

if [ "$BEFORE_DELEGATED" -eq 0 ] && [ "$BEFORE_WALLETS" -eq 0 ]; then
  echo "⚠️ Wallet not found in delegatedWallets/wallets: $WALLET"
  exit 1
fi

cp -f "$CONFIG_FILE" "${CONFIG_FILE}.bak.$(date +%Y%m%d-%H%M%S)"

jq --arg addr_lc "$ADDR_LC" '
  if has("delegatedWallets") then
    .delegatedWallets = ((.delegatedWallets // []) | map(select(((.address // "") | ascii_downcase) != $addr_lc)))
  else . end
  | if has("wallets") then
      .wallets = ((.wallets // []) | map(select(((.address // "") | ascii_downcase) != $addr_lc)))
    else . end
' "$CONFIG_FILE" > "${CONFIG_FILE}.tmp"

mv "${CONFIG_FILE}.tmp" "$CONFIG_FILE"

echo "βœ… Wallet removed: $WALLET"
if jq -e '.delegatedWallets' "$CONFIG_FILE" >/dev/null 2>&1; then
  echo "delegatedWallets count: $(jq '.delegatedWallets | length' "$CONFIG_FILE")"
fi
if jq -e '.wallets' "$CONFIG_FILE" >/dev/null 2>&1; then
  echo "wallets count: $(jq '.wallets | length' "$CONFIG_FILE")"
fi

```



---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### README.md

```markdown
# Pet Operator

Delegate Aavegotchi petting rights to AAI while keeping full ownership.

## What It Does

This repo helps users approve AAI's operator wallet as pet operator on Base:
- AAI operator wallet: `0xb96B48a6B190A9d509cE9312654F34E9770F2110`
- Aavegotchi Diamond: `0xA99c4B08201F2913Db8D28e71d020c4298F29dBF`

Approval call:
- `setPetOperatorForAll(address operator, bool approved)`

## Scripts

- `scripts/check-approval.sh <wallet>`
  - Returns `approved` / `not_approved`
- `scripts/generate-delegation-tx.sh <wallet>`
  - Prints transaction details for `approved=true`
- `scripts/generate-revoke-tx.sh <wallet>`
  - Prints transaction details for `approved=false`
- `scripts/add-delegated-wallet.sh <wallet> [name]`
  - Verifies approval, fetches wallet gotchi IDs, upserts into pet-me-master config (`delegatedWallets`; legacy `wallets` if present)
- `scripts/remove-delegated-wallet.sh <wallet>`
  - Removes wallet from pet-me-master config tracking arrays

## Notes

- This skill does not move NFTs or tokens.
- Users can revoke anytime by sending the revoke transaction.
- Pet-me-master now supports dynamic wallet/delegation discovery; config writes are mainly operational bookkeeping.

```

### _meta.json

```json
{
  "owner": "aaigotchi",
  "slug": "pet-operator",
  "displayName": "Pet Operator",
  "latest": {
    "version": "1.2.0",
    "publishedAt": 1772826827393,
    "commit": "https://github.com/openclaw/skills/commit/9d65f4f094a060836d346f188f03377b380604f2"
  },
  "history": [
    {
      "version": "1.1.0",
      "publishedAt": 1772428338589,
      "commit": "https://github.com/openclaw/skills/commit/d6c81fcf81c4e4f2b3cf8aeafb9e3dd557c625ed"
    }
  ]
}

```

### scripts/lib.sh

```bash
#!/usr/bin/env bash

set -euo pipefail

AAVEGOTCHI_DIAMOND="${AAVEGOTCHI_DIAMOND:-0xA99c4B08201F2913Db8D28e71d020c4298F29dBF}"
AAI_OPERATOR="${AAI_OPERATOR:-0xb96B48a6B190A9d509cE9312654F34E9770F2110}"
BASE_RPC_URL="${BASE_RPC_URL:-https://mainnet.base.org}"
PET_ME_CONFIG_FILE="${PET_ME_CONFIG_FILE:-$HOME/.openclaw/workspace/skills/pet-me-master/config.json}"

err() {
  echo "ERROR: $*" >&2
  exit 1
}

warn() {
  echo "WARN: $*" >&2
}

require_bin() {
  local bin="$1"
  command -v "$bin" >/dev/null 2>&1 || err "Missing required binary: $bin"
}

require_read_tools() {
  require_bin cast
  require_bin jq
}

is_eth_address() {
  [[ "$1" =~ ^0x[0-9a-fA-F]{40}$ ]]
}

normalize_wallet() {
  local wallet="$1"
  is_eth_address "$wallet" || err "Invalid wallet address: $wallet"
  printf '%s\n' "$wallet"
}

to_lower() {
  printf '%s\n' "$1" | tr '[:upper:]' '[:lower:]'
}

set_pet_operator_calldata() {
  local approved="$1"

  case "$approved" in
    true|false)
      ;;
    *)
      err "approved must be true|false"
      ;;
  esac

  if command -v cast >/dev/null 2>&1; then
    local data
    data="$(cast calldata "setPetOperatorForAll(address,bool)" "$AAI_OPERATOR" "$approved" 2>/dev/null || true)"
    if [[ -n "$data" && "$data" == 0x* ]]; then
      printf '%s\n' "$data"
      return 0
    fi
  fi

  if [[ "$approved" == "true" ]]; then
    printf '%s\n' "0xcd675d57000000000000000000000000b96b48a6b190a9d509ce9312654f34e9770f21100000000000000000000000000000000000000000000000000000000000000001"
  else
    printf '%s\n' "0xcd675d57000000000000000000000000b96b48a6b190a9d509ce9312654f34e9770f21100000000000000000000000000000000000000000000000000000000000000000"
  fi
}

check_pet_operator_approved() {
  local wallet="$1"
  local out
  local norm

  wallet="$(normalize_wallet "$wallet")"

  out="$(cast call "$AAVEGOTCHI_DIAMOND" "isPetOperatorForAll(address,address)(bool)" "$wallet" "$AAI_OPERATOR" --rpc-url "$BASE_RPC_URL" 2>/dev/null || true)"
  if [ -z "$out" ]; then
    out="$(cast call "$AAVEGOTCHI_DIAMOND" "isPetOperatorForAll(address,address)" "$wallet" "$AAI_OPERATOR" --rpc-url "$BASE_RPC_URL" 2>/dev/null || true)"
  fi

  norm="$(printf '%s' "$out" | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')"

  case "$norm" in
    true|0x1|0x01|0x0000000000000000000000000000000000000000000000000000000000000001)
      return 0
      ;;
    false|0x0|0x00|0x0000000000000000000000000000000000000000000000000000000000000000)
      return 1
      ;;
    *)
      warn "Unexpected isPetOperatorForAll response: ${out:-<empty>}"
      return 1
      ;;
  esac
}

fetch_wallet_gotchi_ids() {
  local wallet="$1"
  local out

  wallet="$(normalize_wallet "$wallet")"

  out="$(cast call "$AAVEGOTCHI_DIAMOND" "tokenIdsOfOwner(address)(uint32[])" "$wallet" --rpc-url "$BASE_RPC_URL" --json 2>/dev/null || true)"
  if [ -n "$out" ]; then
    printf '%s' "$out" | jq -r '.[0][]? | tostring' 2>/dev/null | sed '/^$/d' || true
    return 0
  fi

  local balance_hex
  local count
  balance_hex="$(cast call "$AAVEGOTCHI_DIAMOND" "balanceOf(address)(uint256)" "$wallet" --rpc-url "$BASE_RPC_URL" 2>/dev/null || true)"
  [ -n "$balance_hex" ] || return 0
  count=$((16#${balance_hex#0x}))

  local i token_hex
  for ((i=0; i<count; i++)); do
    token_hex="$(cast call "$AAVEGOTCHI_DIAMOND" "tokenOfOwnerByIndex(address,uint256)(uint256)" "$wallet" "$i" --rpc-url "$BASE_RPC_URL" 2>/dev/null || true)"
    [ -n "$token_hex" ] || continue
    printf '%s\n' "$((16#${token_hex#0x}))"
  done
}

```

pet-operator | SkillHub