> ## Documentation Index
> Fetch the complete documentation index at: https://docs.caminotreasury.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Yield Distributor

> Claim weekly yield drops via merkle proofs

## Overview

The **YieldDistributor** pays out C0 yield in weekly periods. Each period the operator publishes a merkle root summarizing every holder's share for the prior week; holders then claim their cut by submitting their leaf and proof against that root.

Two function calls cover the holder side:

* `getPeriods` — fetch every period the holder has a leaf in, with status, root, and merkle proof. Resolved entirely client-side from your wagmi `Config` + the public artifact endpoint — no API key needed.
* `claim` — submit one period's claim. The on-chain `claim()` transfers C0 to the leaf's `account` regardless of who signs the transaction.

For the end-to-end walkthrough, see [How to claim yield](/smart-contracts/claim-yield).

## How a period works

Every period moves through three phases:

1. **Published** — the operator commits a merkle root, exclusion list hash, and total amount on-chain. Claims revert with `NotFinalized` during this window.
2. **Finalized** — after a \~24h replace window, claims open. The operator can no longer replace the root.
3. **Expired** — after the claim window closes, unclaimed funds are sweepable to a recipient. Holders can no longer claim that period.

`getPeriods` applies the same phase rules client-side, so any entry it returns with `status: "unclaimed"` is safe to submit immediately.

## Reads

```ts theme={null}
import { createConfig, http } from "@wagmi/core";
import { mainnet } from "@wagmi/core/chains";
import {
  addresses,
  readYieldDistributorPeriods,
  readYieldDistributorPeriodCount,
  readYieldDistributorIsClaimed,
  readYieldDistributorIsFinalized,
  readYieldDistributorIsExpired,
} from "@camino-treasury/sdk";

const config = createConfig({
  chains: [mainnet],
  transports: { [mainnet.id]: http() },
});

const distributor = addresses[mainnet.id].yieldDistributor!;

// How many periods have ever been published.
const count = await readYieldDistributorPeriodCount(config, { address: distributor });

// Full state for a specific period.
const period = await readYieldDistributorPeriods(config, {
  address: distributor,
  args: [0n],
});
// period: [merkleRoot, exclusionListHash, totalAmount, claimed,
//          startBlock, endBlock, publishedAt, finalizedAt, expiresAt]

// Has a specific leaf been claimed?
const claimed = await readYieldDistributorIsClaimed(config, {
  address: distributor,
  args: [0n, 4n], // periodId, leaf index
});

// Phase checks
const finalized = await readYieldDistributorIsFinalized(config, {
  address: distributor,
  args: [0n],
});
const expired = await readYieldDistributorIsExpired(config, {
  address: distributor,
  args: [0n],
});
```

## Claim

The SDK ships two high-level helpers that wrap proof resolution + the on-chain write:

```ts theme={null}
import { claim, getPeriods } from "@camino-treasury/sdk";

const { data: periods } = await getPeriods({
  config,
  chainId: mainnet.id,
  holder: account.address,
});

for (const p of periods) {
  if (p.status !== "unclaimed") continue;
  const hash = await claim({ config, account, period: p });
  // p carries periodId, index, account, amount, proof — everything the
  // on-chain claim() needs.
}
```

`getPeriods` returns `{ data: Period[], count }`. Each `Period` carries its own `status: "claimed" | "unclaimed"`; filter client-side for the entries you want to submit.

If you want to call the contract directly (custom proof source, calldata-only path, etc.) the wagmi-generated entry point is also exported:

```ts theme={null}
import { writeYieldDistributorClaim } from "@camino-treasury/sdk";

const hash = await writeYieldDistributorClaim(config, {
  account,
  address: distributor,
  args: [
    periodId,        // bigint
    BigInt(index),   // bigint
    holderAccount,   // address that receives the C0
    amount,          // bigint, raw 6-decimal C0
    proof,           // bytes32[]
  ],
});
```

`msg.sender` is unconstrained — anyone can submit the claim on a holder's behalf; the funds always go to the `account` embedded in the leaf.

## Watch events

```ts theme={null}
import {
  watchYieldDistributorClaimedEvent,
  watchYieldDistributorPublishedEvent,
  addresses,
} from "@camino-treasury/sdk";

// Stream every claim that lands.
const unwatchClaims = watchYieldDistributorClaimedEvent(config, {
  address: addresses[mainnet.id].yieldDistributor!,
  onLogs: (logs) => {
    for (const log of logs) {
      const { periodId, index, account, amount } = log.args;
      console.log(`period ${periodId} index ${index}: ${amount} → ${account}`);
    }
  },
});

// Stream new period publications.
const unwatchPublish = watchYieldDistributorPublishedEvent(config, {
  address: addresses[mainnet.id].yieldDistributor!,
  onLogs: (logs) => console.log("new period:", logs),
});
```

`Claimed`, `Published`, `Paused`, `Unpaused`, `Swept`, and `RootReplaced` all have matching `watchYieldDistributor*Event` exports — IDE autocomplete on `watchYieldDistributor` will list them. Admin-only events (role changes, parameter updates) are filtered out of the SDK surface.

## Revert reasons

| Error            | Meaning                                                                                          |
| ---------------- | ------------------------------------------------------------------------------------------------ |
| `NotFinalized`   | Period is still in its 24h replace window. Wait for finalization.                                |
| `Expired`        | Claim window has closed. The leaf is no longer claimable.                                        |
| `AlreadyClaimed` | This `(periodId, index)` pair has already been submitted.                                        |
| `InvalidProof`   | Proof doesn't verify against the on-chain root. Check the leaf came from the matching period.    |
| `OverAllocated`  | Per-period cap reached. Indicates a published root with `Σ leaves > totalAmount` — operator bug. |
| `ZeroAddress`    | The leaf's `account` is the zero address.                                                        |
| `EnforcedPause`  | The contract is paused.                                                                          |

## What's next

* [How to claim yield](/smart-contracts/claim-yield) — runnable step-by-step
* [C0 Token](/smart-contracts/c0-token) — read balances and transfer C0
