# Watchtower and Indexer

Optional off-chain components for payment channels: watchtower (dispute response) and indexer (channel listing).

---

## Watchtower

### Purpose

When a channel is in **Dispute**, the party that did not initiate the close has a limited time (challenge window) to submit a **newer** signed state via `challengeClose`. If they are offline, a malicious counterparty could submit an old state and wait for the deadline, then `finalizeClose` and take more than their share.

A **watchtower** watches the chain for `ChallengeSubmitted` (and channel close activity) for channels where a designated participant is involved. If it sees a close that uses an older state than the one the watchtower holds, it submits `challengeClose` with the latest signed state before the deadline.

### Design

- **Inputs**: RPC URL, list of (channelId, latest signed state: nonce, balanceA, balanceB, sigs) for channels the user cares about, and a key that can sign txs (or the watchtower runs on behalf of the user and has delegated authority).
- **Logic**: Subscribe to or poll PaymentChannelManager for `ChallengeSubmitted` and `ChannelClosed`. For each channel in the list, if `ChallengeSubmitted` shows a dispute with `nonce` less than the watchtower’s latest nonce, call `challengeClose` with the stored state before `disputeDeadline`.
- **Security**: The key that signs `challengeClose` must be secure (env var, HSM, or user-backed key). Prefer a dedicated key with no other funds.

### Implementation options

- **Small service**: e.g. `services/watchtower/` in this repo: Node.js or Python script that uses ethers/web3.py, reads config from env, and runs a loop or event subscription.
- **Separate repo**: Standalone watchtower service that supports this contract’s ABI and events.

No watchtower implementation is included in this repo; this doc is the specification. Deploy and run a watchtower only if users need automated dispute response.

---

## Indexer

### Purpose

The frontend “Channels” tab lists channels by calling `getChannelCount` and `getChannelIdByIndex`, then `getChannel` for each. That works for a small number of channels. For many channels or for filtering by participant, an **indexer** can:

- Index `ChannelOpened` and `ChannelClosed` (and optionally `ChallengeSubmitted`).
- Expose an API: e.g. “channels where address X is participantA or participantB”, “channels in status Open/Dispute”.

### Design

- **Events**: `ChannelOpened(channelId, participantA, participantB, depositA, depositB)`, `ChannelClosed(channelId, balanceA, balanceB, cooperative)`, `ChallengeSubmitted(channelId, nonce, balanceA, balanceB, newDeadline)`.
- **Storage**: DB (e.g. Postgres) with tables for channels and events, keyed by chain and channelId.
- **API**: REST or GraphQL: e.g. `GET /channels?chainId=138&participant=0x...`.

### Implementation options

- **Existing Chain-138 / Mainnet indexer**: If the project already has an indexer for the chain, add handlers for PaymentChannelManager events and expose channel queries.
- **Subgraph (The Graph)**: Create a subgraph for PaymentChannelManager and query channels by participant.
- **Custom service**: Small service that subscribes to logs, writes to DB, and serves HTTP.

Document the indexer API and deployment in ops/deployment docs when one is added. Until then, the frontend uses on-chain `getChannelCount` + `getChannelIdByIndex` + `getChannel` only.

---

## Implementation status

- **Watchtower**: A minimal implementation lives in `services/watchtower/`. It subscribes to `ChallengeSubmitted` on PaymentChannelManager and calls `challengeClose` with a newer state from a JSON file before the dispute deadline. See `services/watchtower/README.md`.
- **Indexer**: No indexer or subgraph is implemented yet. Channels are enumerated on-chain by the frontend. To add "channels by participant", implement a custom indexer or The Graph subgraph as described above and expose an API (e.g. `GET /channels?participant=0x...`).

---

## Transaction mirroring (no change)

Channel transactions on **Chain-138** are normal txs. The existing **Transaction Mirroring Service** mirrors them to **TransactionMirror** on Mainnet. No change to that service or contract is required. State anchoring of Chain-138 (including PaymentChannelManager state) is already done by the **State Anchoring Service** and **MainnetTether**.
