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

# Decrypt to Transact

> Decrypt with a verifiable Threshold Network signature for on-chain use

Use `decryptForTx` to reveal a confidential (encrypted) value on-chain: it returns the plaintext together with a Threshold Network signature, so a contract can verify the reveal when you publish it in a transaction.

Common use cases:

* **Unshield a confidential token**: reveal the encrypted amount you're unshielding so the contract can finalize the public transfer.
* **Finalize a private auction / game move**: bids or moves are submitted encrypted, and the winner is revealed later in a verifiable way.

<Note>
  If you only need to show plaintext in your UI (and you do **not** need an on-chain-verifiable signature), use [`decryptForView`](/client-sdk/guides/decrypt-to-view) instead.
</Note>

## Prerequisites

1. [Create and connect a client](/client-sdk/guides/client-setup).
2. Know the on-chain encrypted handle (`ctHash`) you want to decrypt.
3. Determine whether the contract's ACL policy for this `ctHash` requires a [permit](/client-sdk/guides/permits).

<Note>
  `decryptForTx` does not take a `utype`. It always returns the plaintext as a `bigint` because the result is intended to be passed into a transaction. If you need UI-friendly decoding, use [`decryptForView`](/client-sdk/guides/decrypt-to-view).
</Note>

## Permit: when is it needed?

Often, `decryptForTx` is used to reveal a value that the protocol already considers OK to make public. In those cases, the contract's ACL policy can allow anyone to decrypt, and you can use `.withoutPermit()`.

Examples where a permit is **not** needed:

* **Unshielding**: the amount being unshielded is no longer meant to stay secret.
* **Auction/game reveal**: it doesn't matter who submits the reveal — only that the result is verified.

If the ACL policy restricts decryption, you must use `.withPermit(...)`.

## What `decryptForTx` returns

`.execute()` resolves to an object with:

* `ctHash: bigint | string` — the ciphertext handle you decrypted
* `decryptedValue: bigint` — the plaintext value (always a `bigint`)
* `signature: 0x${string}` — the Threshold Network signature as a hex string

## Decrypt (choose permit mode)

<CodeGroup>
  ```typescript No permit theme={null}
  const decryptResult = await client
    .decryptForTx(ctHash)
    .withoutPermit()
    .execute();

  decryptResult.decryptedValue;
  decryptResult.signature;
  ```

  ```typescript Active permit theme={null}
  const decryptResult = await client
    .decryptForTx(ctHash)
    .withPermit()
    .execute();
  ```

  ```typescript Explicit permit theme={null}
  const permit = await client.permits.getOrCreateSelfPermit();

  const decryptResult = await client
    .decryptForTx(ctHash)
    .withPermit(permit)
    .execute();
  ```
</CodeGroup>

After decrypting, see [Writing Decrypt Result to Contract](/client-sdk/guides/writing-decrypt-result) for how to publish or verify the result on-chain.

## Builder API

### `.execute()` — required, call last

Runs the decryption and returns `{ ctHash, decryptedValue, signature }`.

### `.withPermit(...)` — required unless using `.withoutPermit()`

* `.withPermit()` — uses the active permit
* `.withPermit(permitHash)` — fetches a stored permit by hash
* `.withPermit(permit)` — uses the provided permit object

### `.withoutPermit()` — required unless using `.withPermit(...)`

Decrypt via global allowance (no permit). Only works if the contract's ACL policy allows anyone to decrypt that `ctHash`.

### `.setAccount(address)` — optional

Overrides the account used to resolve the active/stored permit.

### `.setChainId(chainId)` — optional

Overrides the chain used to resolve the Threshold Network URL and permits.

## Common pitfalls

* **Permit mode must be selected**: you must call exactly one of `.withPermit(...)` or `.withoutPermit()` before `.execute()`.
* **Wrong chain/account**: permits are scoped to `chainId + account`. If you get an ACL/permit error, double-check the connected chain and account.
