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

# PressKey Events

> Full event matrix, window.presskey API, nonce challenge flow, and integration patterns.

## window\.presskey API

PressKey exposes a typed request interface on the window object:

```typescript theme={null}
// Core request pattern
window.presskey.request({ action: "ACTION_NAME", ...params })

// All confirmed actions:
window.presskey.request({ action: "PING" })
window.presskey.request({ action: "CONNECT" })
window.presskey.request({ action: "GET_WALLET" })
window.presskey.request({ action: "GET_CHAIN_ID" })
window.presskey.request({ action: "SIGN_MESSAGE",   message: "..." })
window.presskey.request({ action: "SIGN_TRANSACTION", tx: {...} })
window.presskey.request({ action: "SUBMIT_CAPSULE",  capsule: {...} })
window.presskey.request({ action: "SUBMIT_SUPPORTING_CAPSULE", capsuleId: "...", data: {...} })
window.presskey.request({ action: "SUBMIT_DISPUTE",  capsuleId: "...", claims: [...] })
window.presskey.request({ action: "SUBMIT_VOTE",     capsuleId: "...", support: true })
window.presskey.request({ action: "GRANT_ROLE",      role: 2, outletSlug: "..." })
window.presskey.request({ action: "VERIFY_OUTLET",   outletSlug: "..." })
window.presskey.request({ action: "LINK_DOMAIN",     domain: "...", outletSlug: "..." })
```

## Nonce Challenge Flow

Every write action follows this path:

```
App requests action
        |
        v
API Gateway issues nonce (single-use, 30s expiry)
        |
        v
PressKey signs nonce locally (key never leaves device)
        |
        v
PressKey returns { signature, sessionToken, address }
        |
        v
App forwards signed payload to Bridge API
        |
        v
Gateway verifies signature + role status
```

## postMessage Event Matrix

PressKey also communicates via `window.postMessage`. All messages follow the shape `{ type: string, payload: object }`.

### Inbound (App to PressKey)

<div className="pc-ev-grid">
  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_ALLOW\_SITE</span>
    <span className="pc-ev-val">Request site permission to interact with PressKey</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_REQUEST</span>
    <span className="pc-ev-val">Request a signed action (vote, publish, role purchase, etc.)</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_FORWARD\_RPC</span>
    <span className="pc-ev-val">Forward an RPC call through PressKey's provider</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_RPC\_REQUEST</span>
    <span className="pc-ev-val">Direct RPC call via PressKey's injected EIP-1193 provider</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_OPEN\_BOND\_APPROVAL</span>
    <span className="pc-ev-val">Open PressKey UI for bond deposit or dissolution approval</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_OPEN\_CAPSULE\_APPROVAL</span>
    <span className="pc-ev-val">Open PressKey UI for Capsule publish approval (30 PRESS fee)</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_OPEN\_SEND\_APPROVAL</span>
    <span className="pc-ev-val">Open PressKey UI for a PRESS token send approval</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_GET\_PENDING\_APPROVAL</span>
    <span className="pc-ev-val">Query the current queue of pending approvals in PressKey</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_APPROVE\_PENDING\_APPROVAL</span>
    <span className="pc-ev-val">Approve a specific pending action in PressKey</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_REJECT\_PENDING\_APPROVAL</span>
    <span className="pc-ev-val">Reject a specific pending action in PressKey</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_REFRESH\_TX\_STATUS</span>
    <span className="pc-ev-val">Request a refresh of the status for a pending transaction</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_GET\_LATEST\_TX</span>
    <span className="pc-ev-val">Fetch the most recent transaction from PressKey history</span>
  </div>
</div>

### Outbound (PressKey to App)

<div className="pc-ev-grid">
  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_EXTENSION</span>
    <span className="pc-ev-val">Extension has loaded and is ready. Payload includes address, roles, balance, and network.</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESSKEY\_PAGE</span>
    <span className="pc-ev-val">Page-level PressKey state update (navigation, context change)</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">PRESS</span>
    <span className="pc-ev-val">General PRESS token event: balance change, transfer confirmed</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">FETCH\_FAILED</span>
    <span className="pc-ev-val">A PressKey-proxied fetch request failed. Check payload for error details.</span>
  </div>

  <div className="pc-ev-row">
    <span className="pc-ev-key">OFFCHAIN\_FAULT</span>
    <span className="pc-ev-val">An off-chain action failed (Bridge error, API timeout, session invalid)</span>
  </div>
</div>

## Integration Example

```typescript theme={null}
class PressKeyAdapter {
  private address: string | null = null;
  ready = false;

  constructor() {
    window.addEventListener("message", this.handle.bind(this));
  }

  private handle(e: MessageEvent) {
    const { type, payload } = e.data ?? {};
    if (type === "PRESSKEY_EXTENSION") {
      this.address = payload.address;
      this.ready = true;
    }
    if (type === "OFFCHAIN_FAULT") console.error("PressKey fault:", payload);
    if (type === "FETCH_FAILED")   console.error("PressKey fetch failed:", payload);
  }

  async connect(): Promise<string> {
    const r = await window.presskey.request({ action: "CONNECT" });
    this.address = r.address;
    return r.address;
  }

  async vote(capsuleId: string, support: boolean) {
    const { signature, sessionToken } = await window.presskey.request({
      action: "SUBMIT_VOTE",
      capsuleId,
      support,
    });

    return fetch(`https://bridge.presschain.io/capsules/${capsuleId}/accept`, {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${sessionToken}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ capsuleId, support, signature }),
    });
  }

  async submitCapsule(data: object) {
    const { signature, sessionToken } = await window.presskey.request({
      action: "SUBMIT_CAPSULE",
      capsule: data,
    });

    return fetch("https://bridge.presschain.io/capsules/create", {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${sessionToken}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ ...data, signature }),
    });
  }
}

// Usage
const pk = new PressKeyAdapter();
await pk.connect();
await pk.vote("247", true);
```

## Modal State Pattern

Standard React state for PressKey-driven modals in portal apps:

```typescript theme={null}
const [showCreateCapsuleModal, setShowCreateCapsuleModal] = useState(false);
const [showRightsModal,        setShowRightsModal]        = useState(false);
const [showDisputeModal,       setShowDisputeModal]       = useState(false);
const [showRoleModal,          setShowRoleModal]          = useState(false);

const [wallet,          setWallet]          = useState(null);
const [walletConnected, setWalletConnected] = useState(false);
const [latestTx,        setLatestTx]        = useState(null);
const [chainId,         setChainId]         = useState(77117002);
const [networkName,     setNetworkName]     = useState("PressChain Testnet");
```

## WordPress Security Boundary

WordPress never handles keys. The signing boundary is strictly:

```
WordPress PHP/JS
      |
      |  POST signed payload only — never raw keys, never RPC
      v
API Gateway (rate limiting, nonce verify, replay protection)
      |
      v
Bridge API -> Protocol Contracts
```

WordPress sees a web API. This is a hard architectural rule, not a best practice.
