# Watch Tx Confirmation

> Notify when a specific Chia transaction (tx_id / spend bundle name) moves from the mempool to confirmed on-chain, or evicts without confirming. Use when the user says they just sent a tx, broadcasted a spend bundle, or asks to be pinged when something confirms. Accepts tx_id, channel, timeout_minutes as arguments for programmatic invocation.

- Skill: `spacetime-technology/watch-tx-confirmation` (Agent Skill)
- Install (CLI): `npx skillmds@latest add spacetime-technology/watch-tx-confirmation`
- Raw SKILL.md: https://api.skillmd.com/api/skills/spacetime-technology/watch-tx-confirmation/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: Spacetime-Technology (https://skillmd.com/u/spacetime-technology)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/spacetime-technology/watch-tx-confirmation

---


# Watch a transaction confirmation

You are watching a specific Chia tx_id (spend bundle name) and notifying when it lands on-chain — or when it evicts without confirming. Stripe-webhook feel for self-custody. Read-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.
- **A notification MCP** — pick whichever is installed (email, push, chat, webhook). If none, write to `~/.chia-skills/alerts/` and surface inline.
- **Bash + Read + Write** — state file management.

## Resolve inputs

You need: `$tx_id`, `$channel`, `$timeout_minutes`.

- `$tx_id` — the spend bundle name as `0x...` hex (32 bytes / 64 hex chars). Required.
- `$channel` — `email`, `push`, `slack`, `discord`, `telegram`, `webhook`, or `auto` (default).
- `$timeout_minutes` — give up watching after this many minutes if neither confirmed nor evicted. Default `120` (two hours, comfortably beyond Chia's mempool TTL).

Resolve: arguments → context → ask user. If `$tx_id` is missing after asking, emit `STATUS: aborted`, `REASON: missing required inputs`.

Validate `$tx_id`:

- Must be 32 bytes hex, with or without leading `0x`. Anything else → `STATUS: failed`, `REASON: invalid tx_id`.

## Load or initialise state

State file: `~/.chia-skills/state/watch-tx-confirmation__<tx_id_no_prefix>.json`.

Shape:

```json
{
  "tx_id": "0x...",
  "first_seen_iso": "2026-05-19T14:33:00Z",
  "first_seen_height": 6532109,
  "last_state": "pending" | "confirmed" | "evicted" | "unseen",
  "confirmed_height": null,
  "skill_version": "0.1.0"
}
```

On first run: record `first_seen_iso = now`, `first_seen_height = current peak`, `last_state = unseen`, write state. (Continue to the check below — first run still does work.)

## Check status

Use chia-explorer to determine the current state of the tx_id in this priority:

1. **Is it in the mempool right now?** If yes → state is `pending`.
2. **Was it confirmed on-chain?** Walk recent blocks since `first_seen_height` looking for a spend bundle whose name matches `$tx_id`. Stop at peak. If found → state is `confirmed` and record the height.
3. **Otherwise** → state is either `unseen` (never observed) or `evicted` (was pending earlier, no longer in mempool, not confirmed).
   - If `last_state` was `pending` and it's no longer in the mempool *and* not confirmed → `evicted`.
   - If `last_state` was `unseen` and it's still nowhere → still `unseen`.

If `(now - first_seen_iso) > $timeout_minutes` and state is still `unseen` or `pending` → treat as timed out.

## Decide whether to notify

Notify only on a *state transition* (the whole point of being schedulable):

| Previous state | New state | Notify? |
|---|---|---|
| any | `confirmed` (first time) | yes |
| `pending` | `evicted` | yes |
| `unseen` | `pending` | optional — only if the user asked to know when it hit the mempool |
| `unseen` | `unseen` | no |
| `pending` | `pending` | no |
| any | timed out | yes (one-shot) |

Default behaviour: only notify on `confirmed`, `evicted`, or `timed out`. Mention "still pending" in the run output but don't send a push.

## Compose the notification

Confirmed example:

```
Chia tx confirmed: 0xdead...beef
  Block height: 6,532,210
  Time to confirm: ~12 minutes
  See: https://www.spacescan.io/spend-bundle/0xdeadbeef...   (if you want to link)
```

Evicted example:

```
Chia tx evicted from mempool: 0xdead...beef
  Was pending since: 2026-05-19 14:33 UTC
  Likely cause: fee too low for inclusion. Rebroadcast with a higher fee.
```

Timed out example:

```
Chia tx watch timed out: 0xdead...beef
  Last state: unseen
  Watched for: 120 minutes
  Action: it may have never been broadcast — check your wallet.
```

Use chia-explorer's puzzle-classification on at least one spend in the bundle (if confirmed) to enrich the message: "This was a take_offer for X CAT" or "This was a plain XCH send".

## Send the notification

Pick a channel by priority (same as `watch-address`). Fall back to inline file at `~/.chia-skills/alerts/` if none available.

## Update state

After successful notify (or fallback write), update `last_state` and, for `confirmed`, `confirmed_height`. Write state atomically.

If new state is terminal (`confirmed`, `evicted`, `timed out`), this watch is done. Tell the user to remove the schedule entry for this tx_id — terminal state means future scheduled runs are wasted work. Emit a `TERMINAL: true` field in the output block to make this obvious.

## Scheduling

This skill is one-shot. Wire to:

- **`schedule` skill / cron** — every minute or two for short waits, every 5–10 minutes for longer.
- **`/loop` skill** — handy if the user wants to babysit a single tx ("I'll wait while it confirms").

## Hard rules

- **Read-only.** Never re-broadcast, never re-sign. If the tx evicted, the user re-broadcasts from their wallet with a higher fee.
- **No retroactive notifications.** First-run state recording is the baseline.
- **Notify on transitions only.** Don't spam the user with a "still pending" alert every minute.

## Recovery patterns

- **chia-explorer call fails.** Don't update state. Emit `STATUS: failed`. Next scheduled run resumes.
- **State file says `confirmed` already.** Skill exits immediately with `STATUS: no_change`, `TERMINAL: true`. Tells the user the schedule is stale.

## Output

```
STATUS: success | no_change | partial | failed | aborted
STATE: pending | confirmed | evicted | timed_out | unseen
CONFIRMED_HEIGHT: <int> | none
CHANNEL: <channel used> | inline | none
TERMINAL: true | false
TX_ID: <full tx_id>
ARTIFACT: <path to inline alert file> | none
REASON: <one line, only when STATUS is failed, partial, or aborted>
```

