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.
window.presskey API
PressKey exposes a typed request interface on the window object:
// 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)
PRESSKEY_ALLOW_SITERequest site permission to interact with PressKey
PRESSKEY_REQUESTRequest a signed action (vote, publish, role purchase, etc.)
PRESSKEY_FORWARD_RPCForward an RPC call through PressKey’s provider
PRESSKEY_RPC_REQUESTDirect RPC call via PressKey’s injected EIP-1193 provider
PRESSKEY_OPEN_BOND_APPROVALOpen PressKey UI for bond deposit or dissolution approval
PRESSKEY_OPEN_CAPSULE_APPROVALOpen PressKey UI for Capsule publish approval (30 PRESS fee)
PRESSKEY_OPEN_SEND_APPROVALOpen PressKey UI for a PRESS token send approval
PRESSKEY_GET_PENDING_APPROVALQuery the current queue of pending approvals in PressKey
PRESSKEY_APPROVE_PENDING_APPROVALApprove a specific pending action in PressKey
PRESSKEY_REJECT_PENDING_APPROVALReject a specific pending action in PressKey
PRESSKEY_REFRESH_TX_STATUSRequest a refresh of the status for a pending transaction
PRESSKEY_GET_LATEST_TXFetch the most recent transaction from PressKey history
Outbound (PressKey to App)
PRESSKEY_EXTENSIONExtension has loaded and is ready. Payload includes address, roles, balance, and network.
PRESSKEY_PAGEPage-level PressKey state update (navigation, context change)
PRESSGeneral PRESS token event: balance change, transfer confirmed
FETCH_FAILEDA PressKey-proxied fetch request failed. Check payload for error details.
OFFCHAIN_FAULTAn off-chain action failed (Bridge error, API timeout, session invalid)
Integration Example
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:
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.