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

# Allowance Voucher

> Delegate decrypt/compute access with an off-chain session key on Solana

# Allowance Voucher

Allowance vouchers (session keys) let a ciphertext owner delegate decrypt/compute access to an ephemeral key for a limited time, entirely off-chain.

<Note>Vouchers are revocable by bumping the sharer's session nonce.</Note>

## Security model

A session voucher grants the holder access to **all** of the sharer's encrypted handles, it is not scoped to a specific program or dApp. Coval checks:

1. The session key signed the decrypt/compute request
2. The sharer signed the voucher (exact warning text, expiry, nonce, decrypter)
3. The **sharer** has an on-chain [allowance](/svm/guide/access-control) PDA for the handle

**To limit exposure:**

* Use the shortest expiry that makes sense (minutes rather than hours or days)
* Call `updateActiveVouchersSessionNonce()` when the session ends
* Never log, persist, or forward the signed voucher beyond the narrowest needed scope

### Wallet signing prompt

The voucher message puts this warning **first** so wallets show it before opaque fields:

<Warning>
  Inco Warning: signing this message may leak your private data, including from
  unrelated apps. Sign only if you fully trust this app.
</Warning>

Do not alter this text, Coval rejects vouchers with a different warning.

Canonical signed message (UTF-8, newline-separated):

```text theme={null}
Inco Warning: signing this message may leak your private data, including from unrelated apps. Sign only if you fully trust this app.
sessionNonce:<nonce>
decrypter:<base58 pubkey>
expiresAt:<unix seconds>
```

## Getting Started

```typescript theme={null}
import { Keypair } from '@solana/web3.js';
import {
  grantSessionKeyAllowanceVoucher,
  signMessageFromKeypair,
} from '@inco/solana-sdk/voucher';

// Alice's wallet (adapter or keypair)
const alice = wallet; // { publicKey, signMessage }

// Ephemeral session key for Bob (or Alice's own background agent)
const sessionKeypair = Keypair.generate();

const voucherWithSig = await grantSessionKeyAllowanceVoucher(
  {
    address: alice.publicKey,
    signMessage: signMessageFromKeypair,
  },
  sessionKeypair.publicKey,
  new Date(Date.now() + 60 * 60 * 1000) // 1 hour
);
```

<Warning>
  Granting a session voucher gives that key unverified access to all of Alice's
  allowed handles for the voucher lifetime (until expiry or nonce revoke).
</Warning>

## Attested Decrypt with Voucher

Bob can decrypt any handle Alice is allowed on, using the session key (no Alice wallet popup per request):

```typescript theme={null}
import {
  decryptWithVoucher,
  signMessageFromKeypair,
} from '@inco/solana-sdk/voucher';
import { Transaction } from '@solana/web3.js';

const result = await decryptWithVoucher([handle], {
  address: sessionKeypair.publicKey,
  signMessage: signMessageFromKeypair(sessionKeypair),
  voucherWithSig,
});

console.log(result.plaintexts[0]);

// Optional: same Ed25519 instructions as wallet-path attested decrypt
const tx = new Transaction();
result.ed25519Instructions.forEach((ix) => tx.add(ix));
tx.add(yourProgramInstruction);
```

## Attested Compute with Voucher

```typescript theme={null}
import { AttestedComputeSupportedOps } from '@inco/solana-sdk/attested-compute';
import {
  attestedComputeWithVoucher,
  signMessageFromKeypair,
} from '@inco/solana-sdk/voucher';

const result = await attestedComputeWithVoucher(
  {
    lhsHandle: handle,
    op: AttestedComputeSupportedOps.Ge,
    rhsPlaintext: 700n,
  },
  {
    address: sessionKeypair.publicKey,
    signMessage: signMessageFromKeypair(sessionKeypair),
    voucherWithSig,
  }
);

console.log(result.result); // "1" or "0"
```

## Attested Reveal with Voucher

Reveal is the same `decryptWithVoucher` call, use `result.plaintexts` for UI display without building an on-chain verification transaction. See [Attested Reveal](/svm/js-sdk/attestations/attested-reveal).

## Revoking a Voucher

```typescript theme={null}
import { updateActiveVouchersSessionNonce } from '@inco/solana-sdk/voucher';

const newNonce = await updateActiveVouchersSessionNonce({
  address: alice.publicKey,
  signMessage: alice.signMessage,
});
```

This invalidates **all** outstanding vouchers for Alice, regardless of expiry.

<Note>
  Selective revoke (per-session-key) is not supported with the default verifier.
  Re-issue new vouchers to keys that should keep access.
</Note>

## How it differs from EVM

|                         | EVM                             | Solana (SVM)                              |
| ----------------------- | ------------------------------- | ----------------------------------------- |
| Voucher signature       | EIP-712 typed data              | Ed25519 `signMessage` (UTF-8)             |
| Request signature       | EIP-712 AttestedDecrypt/Compute | UTF-8 handle / `op:handle:rhs`            |
| Session nonce storage   | On-chain IncoVerifier           | Covalidator-backed nonce (bump API)       |
| ACL check               | `isAllowedWithProof`            | Sharer's allowance PDA                    |
| Custom session verifier | Optional Solidity contract      | Not yet (default expiry + decrypter only) |

For the EVM guide, see [Allowance Voucher (EVM)](/js-sdk/voucher/allowance-voucher).

## API Reference

### `grantSessionKeyAllowanceVoucher(options, decrypter, expiresAt)`

**Parameters:**

* `options.address`: sharer's wallet public key
* `options.signMessage`: sharer's message signer
* `decrypter`: session key public key (`PublicKey` or base58)
* `expiresAt`: `Date` or unix seconds

**Returns:** `Promise<AllowanceVoucherWithSig>`

### `decryptWithVoucher(handles, options)`

Same return type as [Attested Decrypt](/svm/js-sdk/attestations/attested-decrypt) `decrypt()`, authenticated with a session key + voucher.

### `attestedComputeWithVoucher(args, options)`

Same return type as [Attested Compute](/svm/js-sdk/attestations/attested-compute) `attestedCompute()`.

### `updateActiveVouchersSessionNonce(options)`

Bumps the sharer's session nonce and returns the new value as a string.

### Types

```typescript theme={null}
interface AllowanceVoucher {
  warning: string;       // must equal SESSION_KEY_WARNING
  sessionNonce: string;
  decrypter: string;     // base58
  expiresAt: number;     // unix seconds
}

interface AllowanceVoucherWithSig {
  sharer: string;
  voucher: AllowanceVoucher;
  voucherSignature: string; // base58 Ed25519
}
```
