Skip to main content
Permits are EIP-712 signatures that authorize decryption of confidential data. The issuer field identifies who is accessing the data — the issuer must have been granted access on-chain via FHE.allow(handle, address). When a permit is used, CoFHE validates it against the ACL contract to confirm that the issuer has access to the requested encrypted handle. Each permit includes a sealing keypair. The public key is sent to CoFHE so it can re-encrypt the data for the permit holder. The private key stays client-side and is used to unseal the returned data.

When do you need a permit?

  • decryptForView: always requires a permit.
  • decryptForTx: depends on the contract’s ACL policy for that ctHash.
    • If the policy allows anyone to decrypt, you can use .withoutPermit().
    • If the policy restricts decryption, you must use .withPermit(...).

Prerequisites

Create and connect a client. Permits are scoped to a chainId + account.

Quick start

The examples below show two approaches. The client.permits API is the recommended approach — it automatically signs permits with the connected wallet and manages the permit store. The PermitUtils API is a lower-level alternative that gives you direct control over signing and storage.
After this, the active permit is picked up automatically:
  • decryptForView(...).execute() uses the active permit.
  • decryptForTx(...).withPermit().execute() uses the active permit.

Permit types

  • Permit expiration is a unix timestamp in seconds. The default is 7 days from creation.
  • When a permit is created via client.permits.*, it is automatically stored and set as the active permit.

Creating a self permit

A self permit lets you decrypt data that was allowed to your address.

createSelf

getOrCreateSelfPermit

Returns the active self permit if one exists. Otherwise creates and signs a new one. This is the recommended approach for most applications.

Sharing permits

Sharing permits let an issuer delegate their ACL access to a recipient. The recipient can then decrypt the issuer’s data without needing their own FHE.allow.
1

Issuer creates a sharing permit

The issuer creates a sharing permit specifying the recipient’s address.
2

Issuer exports the permit

Export the permit as a JSON blob and share it with the recipient.
The exported JSON does not contain any sensitive data and can be shared via any channel.
Do not share serialize(permit) output — serialization is meant for local persistence and includes the sealing private key.
3

Recipient imports and signs

The recipient imports the exported JSON and signs it with their wallet. On import, a new sealing key is generated for the recipient.

Active permit management

The SDK tracks all stored permits and an active permit hash per chainId + account. Creating or importing a permit via client.permits.* automatically stores it and selects it as active.

List stored permits

Read / select the active permit

Removing permits

Persistence and security

  • The SDK persists permits in a store keyed by chainId + account.
  • In web environments, this store uses localStorage under the key cofhesdk-permits.
  • A stored permit includes the sealing private key. Treat it like a secret.
    • Never share serialized permits with other users.
    • To share access, use PermitUtils.export(...) which strips sensitive fields.