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

# Participants

> How permanent, wallet-bound protocol identities work in Ryvo.

Every wallet that uses Ryvo registers once as a participant. That registration binds one wallet to one stable `participant_id`. The mapping does not recycle, so off-chain systems can treat `wallet -> participant_id` as stable for the life of the deployment.

## What a participant stores

The participant account is Ryvo's long-lived identity record. Each account holds:

| Field                    | Meaning                                                          |
| ------------------------ | ---------------------------------------------------------------- |
| `owner`                  | The wallet that controls the participant                         |
| `participant_id`         | The compact numeric ID used inside signed messages and PDA seeds |
| `token_balances`         | One balance record per allowlisted token                         |
| `inbound_channel_policy` | Whether other parties may open channels to this participant      |
| `bump`                   | PDA bump for canonical address checks                            |

The `token_balances` vector stores available balance, pending-withdrawal state, and withdrawal destination for each token the participant has used. Up to 16 tokens can coexist per participant. See [Account layouts](/reference/accounts) for the exact byte layout.

## Why participants are permanent

The protocol does not let participants close and recreate their accounts. This preserves three simple invariants:

1. `participant_id` stays stable for the life of the deployment.
2. Off-chain services can index users without worrying about ID reuse.
3. Replay protection is simpler because there is no reopened identity for an old signed message to target.

If a team wants a new protocol identity, they use a new wallet.

## Inbound channel policy

Each participant chooses how other parties may open channels to it:

| Policy            | Meaning                                         |
| ----------------- | ----------------------------------------------- |
| `Permissionless`  | Anyone may create a channel to this participant |
| `ConsentRequired` | The payee must sign channel creation            |
| `Disabled`        | New inbound channels are rejected               |

The default is `ConsentRequired`. The policy can be changed later with `update_inbound_channel_policy`.

## Registration

Registration is deliberately small:

```ts theme={null}
await program.methods
  .initializeParticipant()
  .accounts({
    owner: wallet.publicKey,
    feeRecipient,
  } as any)
  .signers([wallet])
  .rpc();
```

After registration, derive the canonical participant PDA from the wallet address and fetch the account whenever you need the stable `participant_id`:

```ts theme={null}
const participantPda = PublicKey.findProgramAddressSync(
  [Buffer.from("participant"), wallet.publicKey.toBytes()],
  program.programId
)[0];

const participant = await program.account.participantAccount.fetch(participantPda);
```

## What participants do not store

Participants are identity and balance containers. They do **not** store:

* whom they are paying
* the latest signed commitments
* operator business logic

That data lives in `ChannelState`, in off-chain systems, or both.

## See also

* [Balances and withdrawals](/core-concepts/balances-and-withdrawals)
* [Payment channels](/core-concepts/payment-channels)
* [Account layouts](/reference/accounts)
