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

# Policy file

> Every field of the node's YAML policy, with defaults.

The policy is what the command-line node runs from. The app writes one for you from its settings. Values
may reference environment variables as `${NAME}`, expanded at start; an unset reference fails with its
file line. `panofx-node policy validate --policy policy.yaml` checks a file and names the line of any error.

Two shapes load. The **single-chain** shape puts `rpc_url`, `chain_id`, `contracts` and `corridors` at
the top; it still works and counts as one chain. The **multi-chain** shape lists networks under `chains:`.
See [Several chains](/resolvers/runbook/multi-chain).

## `node`

| Field                    | Required     | Default          | Meaning                                                                                              |
| ------------------------ | ------------ | ---------------- | ---------------------------------------------------------------------------------------------------- |
| `name`                   | yes          |                  | Shown publicly on the explorer. Letters, digits, space, `.`, `_`, `-`                                |
| `region`                 | no           |                  | Informational                                                                                        |
| `alert_email`            | no           |                  | Private; used only to reach you about your node                                                      |
| `relay_url`              | yes          |                  | `wss://relay-production-f175.up.railway.app/ws/node` for the hosted relay                            |
| `metrics_addr`           | no           | `127.0.0.1:8787` | Local dashboard, Prometheus metrics and the pause/resume control endpoint                            |
| `data_dir`               | no           | `./data`         | Nonce state and other small persisted files                                                          |
| `max_clock_skew_seconds` | no           | `20`             | Decline `clock_skew` when the clock and the chain disagree by more. Solana chains use a higher floor |
| `rpc_url`                | single-chain |                  | The chain's RPC. `"${RPC_URL}"` keeps a keyed URL out of the file                                    |
| `chain_id`               | single-chain |                  | 84532 for Base Sepolia                                                                               |
| `rpc_fallback_urls`      | no           |                  | Tried in order when `rpc_url` fails                                                                  |

## `signer`

| Field      | Meaning                                                                                                                           |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `backend`  | `keyfile`, `turnkey` or `mpcvault`                                                                                                |
| `keyfile`  | Keyfile backend: path to the encrypted keyfile. The passphrase comes from `PANOFX_KEY_PASSPHRASE_FILE` or `PANOFX_KEY_PASSPHRASE` |
| `turnkey`  | `{ organization_id, sign_with, address?, api_public_key, base_url? }`. See [MPC signers](/resolvers/runbook/mpc-signers)          |
| `mpcvault` | `{ vault_uuid, address, client_signer_public_key, base_url? }`                                                                    |

The signer signs EVM offers and is the node's identity with the relay, on every chain.

## `solana_signer`

Required when any chain has `kind: solana`. `{ backend: keyfile, keyfile: ./solana-keyfile.json }`,
created with `panofx-node init --solana` and opened with the same passphrase.

## `chains[]`

| Field                    | Required | Default      | Meaning                                                                                    |
| ------------------------ | -------- | ------------ | ------------------------------------------------------------------------------------------ |
| `name`                   | no       |              | Shown in logs and the dashboard                                                            |
| `kind`                   | no       | `evm`        | `evm` or `solana`                                                                          |
| `chain_id`               | yes      |              | EVM chain id, or 101/102/103/104+ for Solana                                               |
| `rpc_url`                | yes      |              |                                                                                            |
| `rpc_fallback_urls`      | no       |              | Tried in order when `rpc_url` fails                                                        |
| `max_clock_skew_seconds` | no       | node's value | Per-chain override                                                                         |
| `contracts`              | EVM      |              | `{ reactor, validation, executor, permit2? }`. `permit2` defaults to the canonical address |
| `program`                | Solana   |              | The order-engine program id                                                                |
| `corridors`              | yes      |              | At least one                                                                               |

`PANOFX_EXECUTOR` (one EVM chain) or `PANOFX_EXECUTOR_<chain id>` replaces `contracts.executor` at start.

## `corridors[]`

One entry quotes both directions.

| Field                             | Required | Default | Meaning                                                                                                   |
| --------------------------------- | -------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `base_token`                      | yes      |         | `0x` address on EVM, mint on Solana. cNGN                                                                 |
| `quote_token`                     | yes      |         | The dollar token                                                                                          |
| `base_symbol`, `quote_symbol`     | yes      |         | For logs and the dashboard                                                                                |
| `base_decimals`, `quote_decimals` | yes      |         | 6 for cNGN, USDC and USDT                                                                                 |
| `spread_bps`                      | yes      |         | Your margin either side of the reference rate                                                             |
| `min_ticket_base`                 | no       |         | Whole base-token units. Smaller RFQs decline `below_minimum`                                              |
| `max_ticket_base`                 | no       |         | Largest single fill, whole base-token units. Larger RFQs decline `ticket_cap`                             |
| `daily_cap_base`                  | no       |         | Whole base-token units per UTC day. Beyond it, `daily_cap`                                                |
| `inventory_floor`                 | yes      |         | `{ base, quote }` in whole units. A fill that would take a balance under these declines `inventory_floor` |
| `rate`                            | yes      |         | See below                                                                                                 |
| `offer_ttl_seconds`               | no       | `90`    | How long an offer stays valid. At most 120 on Solana; 60 is a good value there                            |

### `rate`

| Field                       | Default | Meaning                                                                                                                     |
| --------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------- |
| `oracle`                    | `false` | `true`: quote the relay's band mid plus your spread                                                                         |
| `static`                    |         | A fixed rate in base units per quote unit, such as `1326.0` naira per dollar                                                |
| `sources`                   |         | Your own rate feeds                                                                                                         |
| `max_age_seconds`           | `30`    | Decline `no_rate` when the rate is older                                                                                    |
| `max_divergence_bps`        |         | For `sources`: the most two sources may disagree                                                                            |
| `max_oracle_divergence_bps` | `300`   | With `static` or `sources`, decline `no_rate` when the rate is further than this from a fresh band. `-1` disables the check |

## Complete examples

`policy.example.yaml` (single chain, Base Sepolia) and `policy.multichain.example.yaml` (Base Sepolia and
Solana devnet) in the `panofx-node` folder are complete, working policies for the hosted relay. The
[runbook](/resolvers/runbook/command-line#write-your-policy-5-minutes) reproduces the first.
