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

# Orchestrator

> Opens, fulfils, cancels and expires orders, and is the only contract the escrow obeys.

The orchestrator owns the order (intent) lifecycle. It checks every rule when an order opens, and it releases escrowed USDC only against a valid claim or the depositor's own release.

## The order

```rust theme={null}
pub struct Intent {
    pub taker: Address,
    pub provider: Address,             // the depositor
    pub amount: i128,                  // 7-decimal USDC
    pub rail: Symbol,
    pub currency: Symbol,              // copied from the depositor's RailTerms
    pub rate_e6: i128,                 // >= RailTerms.min_rate_e6
    pub expected_amount_minor: i128,   // exact fiat the taker will pay
    pub payer_id_hash: BytesN<32>,
    pub status: u32,                   // ACTIVE | FULFILLED | RELEASED_MANUAL | CANCELLED | EXPIRED
    pub created_at: u64,
    pub pay_by: u64,
    pub settle_by: u64,
    pub nullifier: BytesN<32>,
}
```

## `signal_intent`

`signal_intent(taker, provider, amount, rail, rate_e6, expected_amount_minor, payer_id_hash, nonce) -> BytesN<32>`

1. `taker.require_auth()`, and the taker is not the provider.
2. `min_amount ≤ amount ≤ max_amount`.
3. The provider has terms for the rail, or `RailNotAccepted`.
4. `rate_e6 ≥ min_rate_e6`, or `RateBelowMinimum`. `expected_amount_minor ≥ ceil(amount × rate_e6 / 10^13)`, or `FiatBelowRate`.
5. The provider's allowed takers are empty or include the taker, or `TakerNotAllowed`.
6. The retail quota applies to the party that is not a registered LP. Two LPs trade with no quota.
7. The order ID is `sha256(contract ‖ taker ‖ provider ‖ amount ‖ rail ‖ rate_e6 ‖ payer_id_hash ‖ nonce)`. An existing ID fails with `IntentExists`.
8. The escrow address comes from config, never from the caller. The amount is locked.
9. `pay_by = now + pay_window_secs` and `settle_by = pay_by + settle_grace_secs`.

<Accordion title="Worked example: 20 USDC at ₱57.00">
  20 USDC is `amount = 200_000_000`. ₱57.00 is 5,700 centavos, so `rate_e6 = 5_700 × 10^6 = 5_700_000_000`.
  `ceil(200_000_000 × 5_700_000_000 / 10^13) = 114_000` centavos, so the taker pays ₱1,140.00.
</Accordion>

## `fulfill_intent`

`fulfill_intent(intent_hash, claim)`

1. The order is `ACTIVE` and `now ≤ settle_by`.
2. `claims.verify(claim)` passes: a registered verifier key for this network, inside the claim's issue and expiry times.
3. `claim.satisfied` is true, and the claim's policy is the registered policy for the order's rail and direction.
4. The claim's `context_digest` equals the digest the contract rebuilds from the order: order ID, expected amount, currency, payee hash (from the live rail terms, which cannot change while locked), payer hash and the order reference.
5. `claims.consume_nullifier(claim.nullifier)` succeeds, or `NullifierUsed`.
6. `fee = amount × fee_bps / 10_000`. The escrow releases to the taker. Status becomes `FULFILLED`.

## Other exits

| Function | Caller | When | Result |
| - | - | - | - |
| `cancel_intent(intent_hash)` | Taker | `ACTIVE` | USDC unlocks to the depositor |
| `depositor_release(intent_hash)` | Depositor | `ACTIVE`, `now ≤ settle_by` | USDC goes to the taker; status `RELEASED_MANUAL`. Works while paused |
| `expire_intent(intent_hash)` | Anyone | `now > settle_by` | USDC unlocks to the depositor |

## Config and LP registry

```rust theme={null}
pub struct Config {
    pub fee_bps: u32,
    pub pay_window_secs: u64,
    pub settle_grace_secs: u64,
    pub min_amount: i128,
    pub max_amount: i128,
    pub fee_recipient: Address,
    pub escrow: Address,
    pub claims: Address,
}
```

`register_lp(admin, lp)`, `revoke_lp(admin, lp)` and `is_lp(addr)` manage the LP registry. Registration exempts an address from the retail quota. It gives no power over anyone's funds.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.