> For the complete documentation index, see [llms.txt](https://docs.fast.poker/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fast.poker/building-on-the-protocol/signer-matrix.md).

# Signer and capability matrix

> Verified against the public fastpoker IDL (PokerXYdXL2SKNnfGbv1WE7vJHipTpNsfZbZeVvoJLn) released 2026-07-17.

**Six signer roles; this maps each to what it can build.**

> Beta software on mainnet. Examples can fail. Test with small amounts.

## Purpose

This page answers two questions. Who signs each kind of work, and what you can build with only a wallet and an RPC endpoint. Use it to scope an integration before you write code. It tells you plainly where you must add TEE auth, delegated reads on the Ephemeral Rollup, an indexer, or operator infrastructure.

The key list and the deep trust model live in [permissions](/architecture/permissions.md). This page does not duplicate that. It maps signers to capabilities so you can plan.

## When to use / who signs

Six signer roles touch the protocol. Each role signs a distinct class of work. No role can act for another.

| Signer               | Key it holds                                        | Signs                                                                                                                | Cannot do                                                                              |
| -------------------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| Player wallet        | The player's self-custody or embedded Solana wallet | Register, join an SNG pool, register an approved signer, claim funds/rewards, recover legacy cash balances           | Read another player's hole cards, advance another seat, move protocol funds            |
| Approved/session key | Ephemeral key registered on the player's seat       | Prove scoped card-read eligibility and submit that seat's gasless `player_action` and `sng_duel_action` on the ER    | Custody joins, deposits, SOL claims, act for another seat                              |
| Legacy table creator | The wallet that created a retired cash table        | Recover balances, settle eligible table state, and close the old table                                               | Create new cash gameplay, override settlement, read player hole cards, drain the vault |
| Crank / operator     | The operator keypair running the Dealer Service     | Advance tables, deal and reveal through the TEE, settle, distribute prizes, run jackpots, sweep rake, credit rewards | Forge player actions, change payouts, withdraw player balances                         |
| TEE ephemeral key    | A short-lived key held inside the enclave           | Sign deal and reveal instructions, gate scoped card reads                                                            | Sign anything custody-related, persist across rotation                                 |
| Admin                | The protocol multisig (Squads)                      | Set short-lived `ProtocolGuard` pause flags, manage the validator allowlist, registry config                         | Rewrite hands, change payouts, withdraw player funds outside program rules             |

Two roles are easy to confuse. The player wallet signs custody actions. The approved/session key is scoped to one registered seat: it proves private-card read eligibility and signs that seat's gasless ER gameplay/duel actions, but it cannot join, deposit, claim SOL, or spend the wallet's funds. See [tee-deal-reveal](/architecture/tee-deal-reveal.md).

## Inputs and constants

Program IDs the matrix refers to. All values are verified from program source.

| Program                         | Pubkey                                         |
| ------------------------------- | ---------------------------------------------- |
| FastPoker (main)                | `PokerXYdXL2SKNnfGbv1WE7vJHipTpNsfZbZeVvoJLn`  |
| fastpoker\_registry             | `pokerQBdo685uLSkpVSyZ1vWooPYYTUhGkeKAHyCmax`  |
| Permission program (MagicBlock) | `ACLseoPoyC3cBqoUtkbjZ4aDrkurZW86v19pXz2XQnp1` |
| Steel tokenomics program        | `FASTPjXb68fPW9JRYSBS3EDoaT6inz84GoqkPK52dsA9` |
| MagicBlock Delegation program   | `DELeGGvXpWV2fqJUhqcF5ZSYMS4JTLjteaAMARRSaeSh` |

The shared helper exports each of these program IDs and the PDA derivations. Import it from [setup](/building-on-the-protocol/setup.md).

## Steps

Plan an integration by reading down the capability table. Find the row that matches what you want to do. Read across to see what it requires beyond a wallet and an RPC.

A capability needs more than wallet plus RPC when any of these is true.

* It reads private card state. That requires TEE auth and a scoped read.
* It reads live in-hand state during play. That state lives on the Ephemeral Rollup behind delegated accounts.
* It reads aggregated history, stats, or leaderboards. Those are computed by an indexer, not stored on-chain in queryable form.
* It advances or settles a game. That is operator work and needs the Dealer Service infrastructure.

## Capability and trust table

What each capability needs. "Wallet + RPC" means a Solana wallet for signing and a standard L1 RPC for reads and sends, with nothing else.

| Capability                                      | Wallet + RPC | Needs TEE auth | Needs ER / delegated reads | Needs indexer | Needs operator infra |
| ----------------------------------------------- | ------------ | -------------- | -------------------------- | ------------- | -------------------- |
| Register a player (`register_player`)           | Yes          | No             | No                         | No            | No                   |
| Read public table and seat accounts on L1       | Yes          | No             | No                         | No            | No                   |
| Derive any PDA (table, seat, vault, pool)       | Yes          | No             | No                         | No            | No                   |
| Join an SNG pool (`join_sng_pool`)              | Yes          | No             | No                         | No            | No                   |
| Choose PLAY/NEXT CARDS (`sng_duel_action`)      | No           | No             | Yes                        | No            | No                   |
| Deposit for a cash seat (`deposit_for_join`)    | Retired      | No             | No                         | No            | No                   |
| Top up a cash seat (`deposit_topup`)            | Retired      | No             | No                         | No            | No                   |
| Claim a cashout receipt                         | Yes          | No             | No                         | No            | No                   |
| Claim rewards                                   | Yes          | No             | No                         | No            | No                   |
| Read your own hole cards                        | No           | Yes            | No                         | No            | No                   |
| Read live betting state during an active hand   | No           | No             | Yes                        | No            | No                   |
| Submit a player action mid-hand                 | No           | No             | Yes                        | No            | No                   |
| Show lobby stats (VPIP, avg pot, hands/hr)      | No           | No             | No                         | Yes           | No                   |
| Show hand history, profiles, leaderboards       | No           | No             | No                         | Yes           | No                   |
| Deal, reveal, advance, or settle a table        | No           | No             | No                         | No            | Yes                  |
| Distribute SNG prizes, run jackpots, sweep rake | No           | No             | No                         | No            | Yes                  |

## What you cannot do with only wallet and RPC

State this plainly to anyone scoping a thin client.

* You cannot read hole cards. Card reads require a scoped TEE authorization signed by the player or an approved session key. A wallet plus RPC alone returns no plaintext cards. See [tee-deal-reveal](/architecture/tee-deal-reveal.md).
* You cannot read live in-hand state by reading L1 accounts. During an active hand the table, seats, and deck are delegated to the Ephemeral Rollup. You must read the delegated accounts on the ER endpoint, not the stale L1 copy. See [ephemeral-rollups](/architecture/ephemeral-rollups.md).
* You cannot compute lobby stats, profiles, history, or leaderboards from a single RPC call. Those are derived by an indexer that crawls and aggregates protocol events over time. A wallet plus RPC can verify a single account, not produce these aggregates.
* You cannot advance or settle a game by signing as a player. Dealing, revealing, advancing, settling, and prize distribution are operator instructions run by the Dealer Service. They are permissionless, so anyone can run that infrastructure, but a player wallet on its own does not move a hand forward.

Custody is the exception that always holds. Funds move only through program instructions tied to the correct signer. No role, including admin, can withdraw player balances outside program rules. See [permissions](/architecture/permissions.md).

## Example

This reads the public, wallet-plus-RPC surface. It derives the player PDA and a cash table vault, then reads the table account. It does not read cards and does not touch the ER. Those paths need the auth described above.

```ts
// signer-matrix-example.ts
// Runnable: reads only public L1 state with wallet + RPC.
import { Connection, PublicKey } from '@solana/web3.js';
import {
  FASTPOKER_PROGRAM_ID,
  getPlayerPda,
  getTablePda,
  getTableVaultPda,
} from './setup'; // shared helper (fastpoker.ts re-export)

async function main() {
  const connection = new Connection(
    process.env.RPC_URL ?? 'https://api.mainnet-beta.solana.com',
    'confirmed',
  );

  // A wallet pubkey is enough to derive the player PDA. No signing needed to read.
  const wallet = new PublicKey(
    process.env.WALLET ?? '11111111111111111111111111111111',
  );
  const [playerPda] = getPlayerPda(wallet);
  console.log('player PDA:', playerPda.toBase58());

  const playerInfo = await connection.getAccountInfo(playerPda);
  console.log('player registered:', playerInfo !== null);

  // Public table + vault are readable with wallet + RPC alone.
  if (process.env.TABLE_ID) {
    const tableId = Buffer.from(process.env.TABLE_ID, 'hex'); // 32-byte id
    const [tablePda] = getTablePda(tableId);
    const [vaultPda] = getTableVaultPda(tablePda);
    const tableInfo = await connection.getAccountInfo(tablePda);
    console.log('table owner is program:',
      tableInfo?.owner.equals(FASTPOKER_PROGRAM_ID) ?? false);
    console.log('vault PDA:', vaultPda.toBase58());
    // NOTE: hole cards are NOT here. That read needs TEE auth (tee-deal-reveal.md).
    // Live in-hand state is NOT here during play. That read needs the ER endpoint.
  }
}

main().catch((e) => {
  console.error(e);
  process.exit(1);
});
```

## Result

You can now scope any integration by signer. A read-only or value-moving client needs only a wallet and an RPC. A client that shows a player their own cards needs TEE auth. A client that renders a live hand needs ER reads. A stats or history product needs an indexer. A process that advances games needs operator infrastructure. Custody never crosses these lines.

## Pitfalls

* Do not treat an L1 read as live truth during a hand. The ER copy is authoritative while accounts are delegated. The L1 account is stale until commit.
* Do not use the session/approved signer for custody actions. It can submit the registered seat's gasless ER gameplay and duel choices, but joins, deposits, withdrawals, and SOL claims still require the player wallet.
* Do not build fund logic on indexer output. Use the indexer for speed and UX. Read Solana state directly when correctness of balances, vaults, or settlement matters.
* Do not confuse permissionless with trivial. Operator instructions are open to anyone, but running them correctly needs the Dealer Service, TEE access, and ER plumbing. A wallet alone does not advance a hand.
* Do not expect admin to be a custody backstop. `ProtocolGuard` is a scoped, short-lived pause. It cannot rewrite hands or move player funds.

## See also

* [TEE deal and reveal](/architecture/tee-deal-reveal.md)
* [Reading and decoding accounts](/building-on-the-protocol/reading-accounts.md)
* [Permission system](/architecture/permissions.md)
* [State accounts](/architecture/state-accounts.md)
* [Ephemeral Rollups](/architecture/ephemeral-rollups.md)
