Back to skills
SkillHub ClubShip Full StackFull Stack

gotchi-channeling

Channel Aavegotchis on Base via Bankr. Checks cooldown, builds calldata, and submits channel txs safely.

Packaged view

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

Stars
3,126
Hot score
99
Updated
March 20, 2026
Overall rating
C4.5
Composite score
4.5
Best-practice grade
C65.6

Install command

npx @skill-hub/cli install openclaw-skills-gotchi-channeling

Repository

openclaw/skills

Skill path: skills/aaigotchi/gotchi-channeling

Channel Aavegotchis on Base via Bankr. Checks cooldown, builds calldata, and submits channel txs safely.

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack.

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 gotchi-channeling into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/openclaw/skills before adding gotchi-channeling to shared team environments
  • Use gotchi-channeling for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: gotchi-channeling
description: Channel Aavegotchis on Base via Bankr. Checks cooldown, builds calldata, and submits channel txs safely.
homepage: https://github.com/aaigotchi/gotchi-channeling
metadata:
  openclaw:
    requires:
      bins:
        - cast
        - jq
        - curl
      env:
        - BANKR_API_KEY
    primaryEnv: BANKR_API_KEY
---

# gotchi-channeling

Channel Alchemica for configured gotchi/parcel pairs.

## Scripts

- `./scripts/check-cooldown.sh <gotchi-id>`
  - Outputs `ready:0` or `waiting:<seconds>`.
  - Fails if RPC query fails.
- `./scripts/channel.sh <gotchi-id> <parcel-id>`
  - Validates cooldown, submits tx via Bankr, prints tx hash.
- `./scripts/channel-all.sh`
  - Iterates `config.json` pairs and channels only ready gotchis.

## Config

`config.json` keys:
- `realmDiamond`
- `rpcUrl`
- `chainId`
- `channeling[]` entries: `{ "parcelId": "...", "gotchiId": "...", "description": "..." }`

Optional env:
- `GOTCHI_CHANNELING_CONFIG_FILE` override config path.
- `BASE_MAINNET_RPC` overrides `rpcUrl`.

## Bankr API key resolution

1. `BANKR_API_KEY`
2. `systemctl --user show-environment`
3. `~/.openclaw/skills/bankr/config.json`
4. `~/.openclaw/workspace/skills/bankr/config.json`

## Quick use

```bash
./scripts/check-cooldown.sh 9638
./scripts/channel.sh 9638 867
./scripts/channel-all.sh
```

## Safety notes

- Cooldown enforced at 24h (`86400` seconds).
- Scripts fail closed on RPC/config/tool errors.
- Batch mode exits non-zero when any entry fails.


---

## Referenced Files

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

### scripts/check-cooldown.sh

```bash
#!/usr/bin/env bash
# Check Gotchi channeling cooldown status
# Returns: ready:0 or waiting:SECONDS

set -euo pipefail

usage() {
  cat <<USAGE
Usage: ./scripts/check-cooldown.sh <gotchi-id>

Prints one machine-readable line:
  ready:0
  waiting:<seconds>
USAGE
}

if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
  usage
  exit 0
fi

if [ "$#" -ne 1 ]; then
  usage
  exit 1
fi

GOTCHI_ID="$1"
COOLDOWN_SECONDS=86400

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

require_bin cast
require_bin jq
load_config
require_numeric "$GOTCHI_ID" "gotchi-id"

if ! LAST_CHANNELED_HEX="$(cast call "$REALM_DIAMOND" \
  "s_gotchiChannelings(uint256)" \
  "$GOTCHI_ID" \
  --rpc-url "$RPC_URL" 2>/dev/null)"; then
  err "Failed to query cooldown from RPC"
fi

LAST_CHANNELED_DEC="$(cast --to-dec "$LAST_CHANNELED_HEX" 2>/dev/null || true)"
[[ "$LAST_CHANNELED_DEC" =~ ^[0-9]+$ ]] || err "Unexpected cooldown value from contract"

CURRENT_TIME="$(date +%s)"
TIME_SINCE=$((CURRENT_TIME - LAST_CHANNELED_DEC))
TIME_REMAINING=$((COOLDOWN_SECONDS - TIME_SINCE))

if [ "$TIME_REMAINING" -le 0 ]; then
  echo "ready:0"
else
  echo "waiting:$TIME_REMAINING"
fi

```

### scripts/channel.sh

```bash
#!/usr/bin/env bash
# Channel Alchemica for a single Gotchi via Bankr

set -euo pipefail

usage() {
  cat <<USAGE
Usage: ./scripts/channel.sh <gotchi-id> <parcel-id>

Examples:
  ./scripts/channel.sh 9638 867
USAGE
}

if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
  usage
  exit 0
fi

if [ "$#" -ne 2 ]; then
  usage
  exit 1
fi

GOTCHI_ID="$1"
PARCEL_ID="$2"
TRANSFER_TOPIC="0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"

FUD_ADDR="0x2028b4043e6722ea164946c82fe806c4a43a0ff4"
FOMO_ADDR="0xa32137bfb57d2b6a9fd2956ba4b54741a6d54b58"
ALPHA_ADDR="0x15e7cac885e3730ce6389447bc0f7ac032f31947"
KEK_ADDR="0xe52b9170ff4ece4c35e796ffd74b57dec68ca0e5"

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

require_bin cast
require_bin curl
require_bin jq
load_config
require_numeric "$GOTCHI_ID" "gotchi-id"
require_numeric "$PARCEL_ID" "parcel-id"

API_KEY="$(resolve_bankr_api_key)"

echo "🔮 Gotchi Channeling"
echo "===================="
echo "👻 Gotchi: #$GOTCHI_ID"
echo "🏰 Parcel: #$PARCEL_ID"
echo

echo "⏰ Checking cooldown..."
if ! COOLDOWN_RESULT="$($SCRIPT_DIR/check-cooldown.sh "$GOTCHI_ID")"; then
  echo "❌ Cooldown check failed; aborting channel attempt"
  exit 1
fi

if [[ "$COOLDOWN_RESULT" =~ ^ready: ]]; then
  echo "✅ Cooldown ready!"
elif [[ "$COOLDOWN_RESULT" =~ ^waiting:([0-9]+)$ ]]; then
  WAIT_TIME="${BASH_REMATCH[1]}"
  echo "⏰ Not ready yet!"
  echo "   Wait: $(format_wait "$WAIT_TIME")"
  exit 1
else
  err "Unexpected cooldown response: $COOLDOWN_RESULT"
fi

echo
echo "📦 Building transaction..."
CALLDATA="$(cast calldata \
  "channelAlchemica(uint256,uint256,uint256,bytes)" \
  "$PARCEL_ID" \
  "$GOTCHI_ID" \
  0 \
  "0x")"

echo "   Function: channelAlchemica"
echo "   Parcel: $PARCEL_ID"
echo "   Gotchi: $GOTCHI_ID"
echo "   Calldata: ${CALLDATA:0:66}..."
echo

echo "🦞 Submitting to Bankr..."
REQUEST_PAYLOAD="$(jq -n \
  --arg to "$REALM_DIAMOND" \
  --argjson chainId "$CHAIN_ID" \
  --arg data "$CALLDATA" \
  --arg description "Channel Alchemica: Gotchi #$GOTCHI_ID on Parcel #$PARCEL_ID" \
  '{
    transaction: {
      to: $to,
      chainId: $chainId,
      value: "0",
      data: $data
    },
    description: $description,
    waitForConfirmation: true
  }')"

RESPONSE="$(curl -sS -X POST "https://api.bankr.bot/agent/submit" \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d "$REQUEST_PAYLOAD")"

SUCCESS="$(echo "$RESPONSE" | jq -r '.success // false')"

if [ "$SUCCESS" != "true" ]; then
  ERROR_MSG="$(echo "$RESPONSE" | jq -r '.error // .message // "Unknown error"')"
  echo
  echo "============================================"
  echo "❌ CHANNELING FAILED"
  echo "============================================"
  echo "Error: $ERROR_MSG"
  echo
  echo "$RESPONSE" | jq '.'
  exit 1
fi

TX_HASH="$(echo "$RESPONSE" | jq -r '.transactionHash // empty')"
BLOCK="$(echo "$RESPONSE" | jq -r '.blockNumber // "pending"')"

echo

echo "============================================"
echo "✅ CHANNELING SUCCESSFUL!"
echo "============================================"
echo

echo "👻 Gotchi #$GOTCHI_ID channeled on Parcel #$PARCEL_ID"
echo "📦 Block: $BLOCK"
if [ -n "$TX_HASH" ]; then
  echo "🔗 Transaction: $TX_HASH"
  echo "🌐 View: https://basescan.org/tx/$TX_HASH"
fi

echo

echo "💰 Fetching rewards..."

# Reward parsing is best-effort and should never flip a successful tx to failure.
if [ -n "$TX_HASH" ] && RECEIPT="$(cast receipt "$TX_HASH" --rpc-url "$RPC_URL" --json 2>/dev/null)"; then
  extract_amount_hex() {
    local token_addr="$1"
    echo "$RECEIPT" | jq -r --arg topic "$TRANSFER_TOPIC" --arg token "$token_addr" '
      .logs[]? |
      select((.topics[0] // "" | ascii_downcase) == ($topic | ascii_downcase)) |
      select((.address // "" | ascii_downcase) == ($token | ascii_downcase)) |
      .data
    ' | head -1
  }

  to_token_dec() {
    local hex="$1"
    local dec
    if [ -z "$hex" ] || [ "$hex" = "null" ]; then
      printf '0.00'
      return
    fi
    dec="$(cast --to-dec "$hex" 2>/dev/null || echo 0)"
    awk -v n="$dec" 'BEGIN { printf "%.2f", n/1e18 }'
  }

  FUD_HEX="$(extract_amount_hex "$FUD_ADDR")"
  FOMO_HEX="$(extract_amount_hex "$FOMO_ADDR")"
  ALPHA_HEX="$(extract_amount_hex "$ALPHA_ADDR")"
  KEK_HEX="$(extract_amount_hex "$KEK_ADDR")"

  FUD_DEC="$(to_token_dec "$FUD_HEX")"
  FOMO_DEC="$(to_token_dec "$FOMO_HEX")"
  ALPHA_DEC="$(to_token_dec "$ALPHA_HEX")"
  KEK_DEC="$(to_token_dec "$KEK_HEX")"

  TOTAL_DEC="$(awk -v a="$FUD_DEC" -v b="$FOMO_DEC" -v c="$ALPHA_DEC" -v d="$KEK_DEC" 'BEGIN { printf "%.2f", a+b+c+d }')"

  if [ "$TOTAL_DEC" != "0.00" ]; then
    echo "💎 Alchemica Earned:"
    echo "   🔥 FUD:   $FUD_DEC"
    echo "   😱 FOMO:  $FOMO_DEC"
    echo "   🧠 ALPHA: $ALPHA_DEC"
    echo "   💚 KEK:   $KEK_DEC"
    echo "   💰 Total: $TOTAL_DEC Alchemica"
  else
    echo "💎 Alchemica minted! (reward amounts unavailable from receipt parsing)"
  fi
else
  echo "💎 Alchemica minted! (receipt unavailable for reward parsing)"
fi

echo

echo "⏰ Next channel: $(date -u -d '+24 hours' '+%Y-%m-%d %H:%M UTC' 2>/dev/null || echo '24 hours from now')"
echo

echo "LFGOTCHi!"

```

### scripts/channel-all.sh

```bash
#!/usr/bin/env bash
# Channel all configured gotchis

set -euo pipefail

usage() {
  cat <<USAGE
Usage: ./scripts/channel-all.sh

Reads config.json channeling entries and channels all ready gotchis.
USAGE
}

if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
  usage
  exit 0
fi

if [ "$#" -gt 0 ]; then
  usage
  exit 1
fi

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

require_bin jq
load_config

if ! jq -e '.channeling | type == "array" and length > 0' "$CONFIG_FILE" >/dev/null 2>&1; then
  err "No channeling entries in $CONFIG_FILE"
fi

ENTRIES="$(jq -r '.channeling[] | "\(.gotchiId // "")\t\(.parcelId // "")\t\(.description // "")"' "$CONFIG_FILE")"

echo "🔮 Channeling All Gotchis"
echo "========================="
echo

echo "📊 Checking gotchis..."
echo

TOTAL=0
READY=0
WAITING=0
CHANNELED=0
FAILED=0

while IFS=$'\t' read -r GOTCHI_ID PARCEL_ID DESCRIPTION; do
  [ -n "$GOTCHI_ID" ] || continue

  TOTAL=$((TOTAL + 1))
  echo "👻 Gotchi #$GOTCHI_ID (Parcel #$PARCEL_ID)"
  if [ -n "$DESCRIPTION" ]; then
    echo "   📝 $DESCRIPTION"
  fi

  if [[ ! "$GOTCHI_ID" =~ ^[0-9]+$ ]] || [[ ! "$PARCEL_ID" =~ ^[0-9]+$ ]]; then
    echo "   ❌ Invalid gotchiId/parcelId in config"
    FAILED=$((FAILED + 1))
    echo
    continue
  fi

  if ! COOLDOWN_RESULT="$($SCRIPT_DIR/check-cooldown.sh "$GOTCHI_ID" 2>&1)"; then
    echo "   ❌ Cooldown check failed: $COOLDOWN_RESULT"
    FAILED=$((FAILED + 1))
    echo
    continue
  fi

  if [[ "$COOLDOWN_RESULT" =~ ^ready: ]]; then
    READY=$((READY + 1))
    echo "   ✅ Ready to channel"

    LOG_FILE="$(mktemp "/tmp/channel-${GOTCHI_ID}-XXXX.log")"
    if "$SCRIPT_DIR/channel.sh" "$GOTCHI_ID" "$PARCEL_ID" >"$LOG_FILE" 2>&1; then
      CHANNELED=$((CHANNELED + 1))
      echo "   ✅ Channeled successfully"

      REWARDS_LINE="$(grep -E "Total:" "$LOG_FILE" | tail -1 || true)"
      if [ -n "$REWARDS_LINE" ]; then
        echo "   💎 $REWARDS_LINE"
      fi
    else
      FAILED=$((FAILED + 1))
      echo "   ❌ Channeling failed (log: $LOG_FILE)"
    fi
  elif [[ "$COOLDOWN_RESULT" =~ ^waiting:([0-9]+)$ ]]; then
    WAITING=$((WAITING + 1))
    WAIT_TIME="${BASH_REMATCH[1]}"
    echo "   ⏰ Wait $(format_wait "$WAIT_TIME")"
  else
    FAILED=$((FAILED + 1))
    echo "   ❌ Unexpected cooldown output: $COOLDOWN_RESULT"
  fi

  echo
done <<< "$ENTRIES"

echo "============================================"
echo "📊 CHANNELING SUMMARY"
echo "============================================"
echo "Total gotchis: $TOTAL"
echo "Ready: $READY"
echo "Channeled: $CHANNELED"
echo "Failed: $FAILED"
echo "Still waiting: $WAITING"
echo

if [ "$FAILED" -gt 0 ]; then
  echo "⚠️  Completed with failures"
  exit 1
fi

if [ "$CHANNELED" -gt 0 ]; then
  echo "✅ Successfully channeled $CHANNELED gotchi(s)!"
elif [ "$READY" -eq 0 ]; then
  echo "⏰ No gotchis ready to channel yet"
else
  echo "⚠️  No channels were submitted"
fi

echo

echo "LFGOTCHi!"

```



---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### README.md

```markdown
# Gotchi Channeling

Automate Aavegotchi Alchemica channeling on Base via Bankr wallet submission.

## Scripts

- `./scripts/check-cooldown.sh <gotchi-id>`
  - Returns `ready:0` or `waiting:<seconds>`
- `./scripts/channel.sh <gotchi-id> <parcel-id>`
  - Channels one gotchi if cooldown is ready
- `./scripts/channel-all.sh`
  - Reads `config.json` and channels all ready entries

## Requirements

- `cast` (Foundry)
- `jq`
- `curl`
- Bankr API key

Bankr API key resolution order:
1. `BANKR_API_KEY`
2. user systemd environment (`systemctl --user show-environment`)
3. `~/.openclaw/skills/bankr/config.json`
4. `~/.openclaw/workspace/skills/bankr/config.json`

## Config

Default config path: `./config.json`
Override path: `GOTCHI_CHANNELING_CONFIG_FILE=/path/to/config.json`

Example:

```json
{
  "realmDiamond": "0x4B0040c3646D3c44B8a28Ad7055cfCF536c05372",
  "rpcUrl": "https://mainnet.base.org",
  "chainId": 8453,
  "channeling": [
    {
      "parcelId": "867",
      "gotchiId": "9638",
      "description": "Primary pair"
    }
  ]
}
```

## Notes

- Cooldown is 24h (`86400` seconds).
- `channel.sh` fails closed if cooldown/RPC checks fail.
- `channel-all.sh --help` is non-destructive.

```

### _meta.json

```json
{
  "owner": "aaigotchi",
  "slug": "gotchi-channeling",
  "displayName": "Gotchi Channeling",
  "latest": {
    "version": "0.2.0",
    "publishedAt": 1772826838966,
    "commit": "https://github.com/openclaw/skills/commit/430d7525c4786ed04852a1ca4c56611280fc59bf"
  },
  "history": [
    {
      "version": "0.1.0",
      "publishedAt": 1771648557060,
      "commit": "https://github.com/openclaw/skills/commit/32270de1cdbe1e822a3a27c857c7a417c606a033"
    }
  ]
}

```

### references/FUNCTION_SEARCH.md

```markdown
# Finding channelAlchemica Function

## Contract Info
- **Contract:** Aavegotchi Diamond (Base)
- **Address:** 0xA99c4B08201F2913Db8D28e71d020c4298F29dBF
- **Chain:** Base (8453)

## Possible Function Signatures

Based on Aavegotchi documentation, the function likely has one of these signatures:

### Option 1: Single Parameter (Gotchi ID only)
```solidity
function channelAlchemica(uint256 _gotchiId) external
```
- **Selector:** `0x38d0b418`
- **Use case:** Channel using gotchi on your default parcel

### Option 2: Two Parameters (Realm + Gotchi)
```solidity
function channelAlchemica(uint256 _realmId, uint256 _gotchiId) external
```
- **Selector:** `0x7e27b66f`
- **Use case:** Specify which parcel to channel on

### Option 3: Three Parameters (Realm + Gotchi + Installation)
```solidity
function channelAlchemica(uint256 _realmId, uint256 _gotchiId, uint256 _installationId) external
```
- **Selector:** `0x356dedfb`
- **Use case:** Specify exact Aaltar installation

## How to Find The Real One

### Method 1: Manual Channel Transaction
1. Go to https://verse.aavegotchi.com
2. Channel Gotchi #9638 manually
3. Check transaction on BaseScan
4. View "Input Data" to see actual function call

### Method 2: Contract ABI
- Check BaseScan verified contract
- Look for channelAlchemica in read/write functions
- Extract exact signature

### Method 3: GitHub Source
- Repository: aavegotchi/aavegotchi-realm-diamond
- File: contracts/RealmDiamond/facets/AlchemicaFacet.sol
- Search for: `function channelAlchemica`

## Next Steps

Once we find the correct function:
1. Update `scripts/channel.sh` with correct selector
2. Test with Gotchi #9638 on Parcel #867
3. Verify transaction succeeds
4. Add to automated daily channeling

## Resources

- [Aavegotchi Contracts](https://wiki.aavegotchi.com/en/contracts)
- [Gotchiverse Bible Chapter 3](https://blog.aavegotchi.com/gotchiverse-bible-chapter-3/)
- [BaseScan Contract](https://basescan.org/address/0xA99c4B08201F2913Db8D28e71d020c4298F29dBF)

---

**Status:** Searching for function signature...
**Date:** 2026-02-20

```

### references/FUNCTION_SIGNATURE.md

```markdown
# channelAlchemica Function Signature

## ✅ FOUND!

**Contract:** Aavegotchi REALM Diamond  
**Source:** https://github.com/aavegotchi/aavegotchi-realm-diamond  
**File:** contracts/RealmDiamond/facets/AlchemicaFacet.sol

## Function Signature

```solidity
function channelAlchemica(
    uint256 _realmId, 
    uint256 _gotchiId,
    uint256 _lastChanneled,
    bytes memory _signature
) external diamondPaused gameActive
```

**Function Selector:** `cast sig "channelAlchemica(uint256,uint256,uint256,bytes)"`

## Parameters

1. **_realmId** (uint256) - Your REALM parcel token ID
   - Example: 867 (your parcel)

2. **_gotchiId** (uint256) - Your Aavegotchi token ID  
   - Example: 9638

3. **_lastChanneled** (uint256) - Timestamp of last channeling for this gotchi
   - Get from: `s.gotchiChannelings[_gotchiId]`
   - First time: 0

4. **_signature** (bytes) - Backend signature for anti-bot protection
   - **⚠️ CRITICAL:** Requires backend API call to get signature
   - Signature validates: keccak256(abi.encodePacked(_realmId, _gotchiId, _lastChanneled))

## Key Requirements

### 1. **24-Hour Cooldown**
```solidity
if (s.lastChanneledDay[_gotchiId] == block.timestamp / (60 * 60 * 24)) 
    revert("AlchemicaFacet: Gotchi can't channel yet");
```

### 2. **Aaltar Must Be Equipped**
```solidity
require(altarLevel > 0, "AlchemicaFacet: Must equip Altar");
```

### 3. **Parcel Cooldown (Aaltar Level Dependent)**
```solidity
require(
    block.timestamp >= s.parcelChannelings[_realmId] + s.channelingLimits[altarLevel], 
    "AlchemicaFacet: Parcel can't channel yet"
);
```

### 4. **Backend Signature Validation**
```solidity
require(
    LibSignature.isValid(
        keccak256(abi.encodePacked(_realmId, _gotchiId, _lastChanneled)), 
        _signature, 
        s.backendPubKey
    ),
    "AlchemicaFacet: Invalid signature"
);
```

## ⚠️ BLOCKER: Backend Signature Required

**The function REQUIRES a signature from Aavegotchi's backend server.**

This signature:
- Prevents botting/automation
- Validates the channeling request
- Cannot be generated without access to backend private key

## Solutions

### Option 1: Use Gotchiverse UI (Manual)
- Visit https://verse.aavegotchi.com
- Gotchiverse frontend calls backend API to get signature
- Click "Channel" button - signature included automatically

### Option 2: Reverse Engineer Backend API (Advanced)
- Monitor network traffic in Gotchiverse
- Find the backend API endpoint for signatures
- Call it programmatically before channeling
- **Risk:** API may have rate limits or require auth

### Option 3: Browser Automation (Hybrid)
- Use Selenium/Puppeteer to automate Gotchiverse UI
- Let frontend handle signature fetching
- Programmatically click "Channel" button

### Option 4: Contact Aavegotchi Team
- Request official API access for channeling
- Explain automation use case
- Get authorized signature endpoint

## Recommended Path Forward

**For now:** The skill **cannot** do fully autonomous channeling due to the signature requirement.

**Alternative:** Build a **channeling reminder** skill instead:
- Check if channeling is available (read-only)
- Notify you when ready to channel
- Provide direct link to Gotchiverse
- Track your channeling history

## Updated Skill Scope

Instead of autonomous channeling, we can build:

1. **Channeling Status Checker**
   - Check 24h cooldown
   - Verify Aaltar equipped
   - Calculate next available time

2. **Channeling Reminder System**
   - Daily notifications
   - "Ready to channel!" alerts
   - One-click link to Gotchiverse

3. **Channeling History Tracker**
   - Log when you channel
   - Track rewards earned
   - Calculate total Alchemica farmed

Would you like me to pivot the skill to this approach?

---

**Date:** 2026-02-20  
**Status:** Function found, signature blocker identified  
**Next:** Redesign skill as reminder/tracker system

```

### scripts/lib.sh

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

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="${GOTCHI_CHANNELING_CONFIG_FILE:-$SCRIPT_DIR/../config.json}"

DEFAULT_REALM_DIAMOND="0x4B0040c3646D3c44B8a28Ad7055cfCF536c05372"
DEFAULT_RPC_URL="https://mainnet.base.org"
DEFAULT_CHAIN_ID="8453"

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

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

require_numeric() {
  local value="$1"
  local label="$2"
  [[ "$value" =~ ^[0-9]+$ ]] || err "Invalid $label: $value"
}

load_config() {
  [ -f "$CONFIG_FILE" ] || err "Config file not found: $CONFIG_FILE"

  REALM_DIAMOND="$(jq -r '.realmDiamond // empty' "$CONFIG_FILE")"
  RPC_URL="$(jq -r '.rpcUrl // empty' "$CONFIG_FILE")"
  CHAIN_ID="$(jq -r '.chainId // empty' "$CONFIG_FILE")"

  [ -n "$REALM_DIAMOND" ] || REALM_DIAMOND="$DEFAULT_REALM_DIAMOND"
  [ -n "$RPC_URL" ] || RPC_URL="$DEFAULT_RPC_URL"
  [ -n "$CHAIN_ID" ] || CHAIN_ID="$DEFAULT_CHAIN_ID"

  if [ -n "${BASE_MAINNET_RPC:-}" ]; then
    RPC_URL="$BASE_MAINNET_RPC"
  fi

  [[ "$REALM_DIAMOND" =~ ^0x[0-9a-fA-F]{40}$ ]] || err "Invalid realmDiamond in config"
  require_numeric "$CHAIN_ID" "chainId"
}

resolve_bankr_api_key() {
  local key="${BANKR_API_KEY:-}"

  if [ -z "$key" ] && command -v systemctl >/dev/null 2>&1; then
    key="$(systemctl --user show-environment 2>/dev/null | sed -n 's/^BANKR_API_KEY=//p' | head -n1 || true)"
  fi

  if [ -z "$key" ] && [ -f "$HOME/.openclaw/skills/bankr/config.json" ]; then
    key="$(jq -r '.apiKey // empty' "$HOME/.openclaw/skills/bankr/config.json" 2>/dev/null || true)"
  fi

  if [ -z "$key" ] && [ -f "$HOME/.openclaw/workspace/skills/bankr/config.json" ]; then
    key="$(jq -r '.apiKey // empty' "$HOME/.openclaw/workspace/skills/bankr/config.json" 2>/dev/null || true)"
  fi

  [ -n "$key" ] || err "BANKR_API_KEY missing (env/systemd/bankr config)"
  printf '%s\n' "$key"
}

format_wait() {
  local seconds="$1"
  local hours mins
  hours=$((seconds / 3600))
  mins=$(((seconds % 3600) / 60))
  printf '%sh %sm' "$hours" "$mins"
}

```

gotchi-channeling | SkillHub