Watch the Chia strategic reserve
You are watching the 21M XCH strategic reserve (the "prefarm") for new outflows and notifying when XCH leaves to a partner, market maker, exchange, or unknown destination. Mainnet only.
This skill follows the conventions in this repo's SKILLS.md. Read that if anything below is unclear.
Required capabilities
- chia-explorer (
mcp__chia-explorer__*) — mandatory. The prefarm tools (get_prefarm_status,get_prefarm_spends,list_prefarm_addresses) are what power this skill. - A notification MCP — pick whichever is installed. Fall back to
~/.chia-skills/alerts/.
Resolve inputs
You need: $min_amount, $channel, $wallet.
$min_amount— minimum XCH per outflow to alert on. Default0(every spend). Common settings:10000(only sizeable moves),100000(only major moves).$channel— notification channel, defaultauto.$wallet— filter to a specific custody wallet (Swiss cold, treasury hot, etc.) by name or address. Defaultall.
Resolve: arguments → context → ask user.
Load or initialise state
State file: ~/.chia-skills/state/watch-prefarm-spend.json. (Single file — there's only one strategic reserve.)
Shape:
{
"last_height": 6532109,
"last_seen_iso": "2026-05-19T14:33:00Z",
"min_amount": 0,
"wallet_filter": "all",
"skill_version": "0.1.0"
}
On first run: record current chain peak as last_height, write state, emit STATUS: success, EVENTS: 0 with "prefarm watch started — future runs will report spends since now". Don't scan history.
Look up new spends
Call chia-explorer's get_prefarm_spends with start_height = last_height + 1 and end_height = current_peak. Apply $min_amount and $wallet filters client-side after fetching.
For each spend, the tool returns:
- the spend's height
- the source custody wallet
- the destination address (raw bech32m)
- the destination label (
partner: Stably,market_maker: GSR,exchange: HTX, etc., orunknown) - the amount in mojos
Drop any spend where amount_xch < $min_amount or whose source wallet doesn't match $wallet (if filter set).
Enrich with fiat
Fetch the current XCH/USD price once and apply to each outflow amount for the message body. Don't make per-spend price calls.
Compose the notification
Chia prefarm spend — 3 new outflows since block 6,532,109
block 6,532,217 100,000 XCH (~$5,000,000)
from: swiss_cold
to: xch1abc...xyz (exchange: HTX)
block 6,532,219 50,000 XCH (~$2,500,000)
from: us_cold
to: xch1def...uvw (market_maker: GSR)
block 6,532,224 2,500 XCH (~$125,000)
from: treasury_hot
to: xch1ghi...rst (unknown)
Total this run: 152,500 XCH (~$7,625,000)
Reserve remaining: 19,847,500 XCH
For "unknown" destinations, add a one-line hint: "Not in chia-explorer's registry — could be a new partner or a regular treasury operation."
Send the notification
Pick a channel by priority. Fall back to inline.
For multi-event runs, the message can be long; if the channel has a hard length limit (Discord 2000, Slack 4000), trim to the first 10 events and note "+N more not shown".
Update state
Set last_height = post_scan_peak, last_seen_iso = now. Atomic write.
If channel failed, still update state and emit STATUS: partial.
Scheduling
This skill is one-shot. Wire to:
scheduleskill / cron — once an hour is plenty. The reserve doesn't move often.- Daily digest mode — schedule once a day and let the skill batch a day's spends into one message.
Hard rules
- Mainnet only. The prefarm registry has no testnet equivalent.
- No retroactive alerts on first run.
- Don't editorialise. Report the move, name the labelled destination, don't speculate on "unknown" beyond noting it's not in the registry.
- Don't claim a destination is
unknownif chia-explorer's registry has a match. Always pass the registry label through.
Recovery patterns
- chia-explorer call fails. Don't update state. Emit
STATUS: failed. - No spends in the window. Update
last_heightto current peak and emitSTATUS: no_change,EVENTS: 0.
Output
STATUS: success | no_change | partial | failed | aborted
EVENTS: <count of spends reported>
TOTAL_XCH: <sum of XCH this run>
RESERVE_REMAINING_XCH: <total still in custody>
CHANNEL: <channel used> | inline | none
LAST_HEIGHT: <height written to state>
ARTIFACT: <path to inline alert file> | none
REASON: <one line, only when STATUS is failed, partial, or aborted>