> ## 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.

# Payment rails

> How a Wise transfer becomes a claim that can settle exactly one Pesa order.

A payment rail is one profile and one policy. Wise is the first rail. One profile per direction proves one outgoing Wise transfer from the payer's own session.

## What the Wise policy proves

| Check | Buy (the user proves) | Sell (the LP proves) |
| - | - | - |
| Record | One transfer-detail reply, every read key unique | Same |
| Status | Final success for a Wise-to-Wise transfer | Final success for the payout (Wise or bank) |
| Funding | From the payer's Wise balance (no card, no bank debit) | Any |
| Payee | A Wise account whose canonical identity hashes to `payee_id_hash` | A Wise or bank account whose identity hashes to `payee_id_hash` |
| Payer | The user's Wise account, hashed to `payer_id_hash` | The LP's Wise account, hashed to `payer_id_hash` |
| Amount | `Equals` the order's exact expected amount, as Wise writes it | Same |
| Currency | Equals the order's currency | Same |
| Reference | Equals the reference derived from the order ID | Same |
| Nullifier | `H(zktls.nullifier.v1 ‖ lp("wise") ‖ lp(transfer_id))` | Same |

## Why each check is there

* **Exact amount, not a range.** The order fixes the exact fiat amount when it opens, so the proof can use a simple equality on the string Wise returns.
* **The reference proves the time.** The reference is derived from the order ID, which did not exist before the order opened. A matching reference shows the payment came after the order. No timestamp check is needed.
* **Identities are hashed on the phone.** Payee and payer are compared by hash. Account numbers never appear in a claim or on-chain.
* **One record.** Every field comes from one authenticated transfer record. Fields cannot be stitched together from different replies.
* **Final status only.** A pending, scheduled or "sent" state is not a completed payment for a buy.

## Canonical identities

The payee hash the depositor sets on-chain and the hash the circuit computes from the Wise record must match byte for byte. One canonical identity function is defined in the Pesa SDK and mirrored in Rust, with a shared test vector from a real capture.

## What does not count as proof

A screenshot, an editable memo, a debit alone, or a submitted or pending transfer never proves completion. If a rail cannot show the actual sender, recipient, amount, currency, a stable transaction ID and a final status, it cannot release escrow automatically. The depositor can still release by hand.

## Adding a rail

A new rail is a new profile and policy pair in the signed policy bundle, plus a registered policy for that rail in the orchestrator. No enclave, verifier, SDK or contract code changes.


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