> ## 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.

# Attested Compute

> Compare encrypted handles off-chain and verify the result on-chain

# Attested Compute

Attested Compute evaluates a comparison on an encrypted handle **off-chain** and returns a covalidator-signed result (`"0"` or `"1"`) plus an Ed25519 instruction for on-chain verification.

Use this when you need a predicate (for example `balance > 100`) without decrypting the raw value, and optionally want to prove that result on-chain.

<Note>
  Only addresses that have been [allowed](/svm/guide/access-control) on the handle can request attested compute. The covalidator checks the on-chain allowance PDA before decrypting.
</Note>

## Import

```typescript theme={null}
import {
  attestedCompute,
  AttestedComputeSupportedOps,
} from '@inco/solana-sdk/attested-compute';
import { handleToBuffer, plaintextToBuffer } from '@inco/solana-sdk/utils';
import { Transaction, SYSVAR_INSTRUCTIONS_PUBKEY } from '@solana/web3.js';
```

## Basic Usage

```typescript theme={null}
import {
  attestedCompute,
  AttestedComputeSupportedOps,
} from '@inco/solana-sdk/attested-compute';
import { Transaction } from '@solana/web3.js';

// Off-chain: is encryptedBalance > 100?
const result = await attestedCompute(
  {
    lhsHandle: balanceHandle, // decimal string u128 handle
    op: AttestedComputeSupportedOps.Gt,
    rhsPlaintext: 100n,
  },
  {
    address: wallet.publicKey,
    signMessage: wallet.signMessage,
  }
);

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

// Optional: verify the attested result on-chain
const tx = new Transaction();
tx.add(result.ed25519Instruction);
tx.add(yourProgramInstruction);
```

## How It Works

```mermaid theme={null}
sequenceDiagram
    participant Client
    participant Covalidator
    participant Solana

    Client->>Client: Sign auth message<br/>op:handle:rhs
    Client->>Covalidator: POST getComputeAttested
    Covalidator->>Solana: Check allowance PDA
    alt Allowed
        Covalidator->>Covalidator: Decrypt handle in TEE
        Covalidator->>Covalidator: Evaluate lhs op rhs
        Covalidator->>Covalidator: Sign SHA256(handle || result)
        Covalidator-->>Client: result + Ed25519 signature
        Client->>Solana: TX with Ed25519 IX + program IX
        Solana->>Solana: Verify signature, run program
    else Not allowed
        Covalidator-->>Client: 403 Forbidden
    end
```

1. Your wallet signs `${op}:${lhsHandle}:${rhsPlaintext}` to prove control of `address`
2. Covalidator verifies the signature and the on-chain allowance for `(handle, address)`
3. Covalidator decrypts the handle, runs the comparison, and signs `SHA256(handle || result)` (same attestation format as [Attested Decrypt](/svm/js-sdk/attestations/attested-decrypt))
4. The SDK returns the boolean result and an `ed25519Instruction` you can prepend to an on-chain verification transaction

***

## Supported Operations

| Name                  | Op                               | Returns       |
| --------------------- | -------------------------------- | ------------- |
| Equal                 | `AttestedComputeSupportedOps.Eq` | `"1"` / `"0"` |
| Not equal             | `AttestedComputeSupportedOps.Ne` | `"1"` / `"0"` |
| Greater than or equal | `AttestedComputeSupportedOps.Ge` | `"1"` / `"0"` |
| Greater than          | `AttestedComputeSupportedOps.Gt` | `"1"` / `"0"` |
| Less than or equal    | `AttestedComputeSupportedOps.Le` | `"1"` / `"0"` |
| Less than             | `AttestedComputeSupportedOps.Lt` | `"1"` / `"0"` |

`rhsPlaintext` is a scalar (`bigint` or `boolean`). Booleans are normalized to `1n` / `0n`.

***

## Example: Credit Check Without Revealing the Score

```typescript theme={null}
import {
  attestedCompute,
  AttestedComputeSupportedOps,
} from '@inco/solana-sdk/attested-compute';
import { handleToBuffer, plaintextToBuffer } from '@inco/solana-sdk/utils';
import { Transaction, SYSVAR_INSTRUCTIONS_PUBKEY } from '@solana/web3.js';

// creditScoreHandle must already be allowed for wallet.publicKey
const result = await attestedCompute(
  {
    lhsHandle: creditScoreHandle,
    op: AttestedComputeSupportedOps.Ge,
    rhsPlaintext: 700n,
  },
  {
    address: wallet.publicKey,
    signMessage: wallet.signMessage,
  }
);

if (result.result !== '1') {
  throw new Error('Credit check failed');
}

// Build on-chain verification (program verifies Ed25519 via instructions sysvar)
const programInstruction = await program.methods
  .verifyDecryption(
    1,
    [handleToBuffer(result.handle)],
    [plaintextToBuffer(result.result)]
  )
  .accounts({
    authority: wallet.publicKey,
    instructions: SYSVAR_INSTRUCTIONS_PUBKEY,
  })
  .instruction();

const tx = new Transaction();
tx.add(result.ed25519Instruction);
tx.add(programInstruction);

const { blockhash } = await connection.getLatestBlockhash();
tx.recentBlockhash = blockhash;
tx.feePayer = wallet.publicKey;

const signedTx = await wallet.signTransaction(tx);
const signature = await connection.sendRawTransaction(signedTx.serialize());
await connection.confirmTransaction(signature, 'confirmed');
```

This is equivalent to evaluating `creditScore >= 700` without ever revealing the raw score to the client as a plaintext integer.

***

## React Integration

```tsx theme={null}
import { useWallet } from '@solana/wallet-adapter-react';
import {
  attestedCompute,
  AttestedComputeError,
  AttestedComputeSupportedOps,
} from '@inco/solana-sdk/attested-compute';
import { useState } from 'react';

function CreditCheck({ handle }: { handle: string }) {
  const wallet = useWallet();
  const [passed, setPassed] = useState<boolean | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const runCheck = async () => {
    if (!wallet.publicKey || !wallet.signMessage) {
      setError('Please connect your wallet');
      return;
    }

    setLoading(true);
    setError(null);

    try {
      const result = await attestedCompute(
        {
          lhsHandle: handle,
          op: AttestedComputeSupportedOps.Ge,
          rhsPlaintext: 700n,
        },
        {
          address: wallet.publicKey,
          signMessage: wallet.signMessage,
        }
      );
      setPassed(result.result === '1');
    } catch (err) {
      if (err instanceof AttestedComputeError) {
        setError(err.message);
      } else {
        setError('Attested compute failed');
      }
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <button onClick={runCheck} disabled={loading || !wallet.connected}>
        {loading ? 'Checking...' : 'Check eligibility'}
      </button>
      {passed !== null && (
        <p>{passed ? 'Eligible' : 'Not eligible'}</p>
      )}
      {error && <p>{error}</p>}
    </div>
  );
}
```

***

## API Reference

### `attestedCompute(args, options)`

**Parameters:**

* `args`: `AttestedComputeArgs`
* `options`: `AttestedComputeOptions`

**Returns:** `Promise<AttestedComputeResult>`

### Types

```typescript theme={null}
interface AttestedComputeArgs {
  lhsHandle: string;                 // Decimal u128 handle string
  op: AttestedComputeOP;             // eq | ne | ge | gt | le | lt
  rhsPlaintext: bigint | boolean;    // Scalar right-hand side
}

interface AttestedComputeOptions {
  address: string | PublicKey;
  signMessage: (message: Uint8Array) => Promise<Uint8Array>;
  endpoint?: string; // Optional covalidator URL override (local testing)
}

interface AttestedComputeResult {
  result: string;                    // "0" | "1"
  handle: string;
  op: AttestedComputeOP;
  rhsPlaintext: bigint;
  ed25519Instruction: TransactionInstruction;
  signature: string;                 // base58 covalidator signature
}
```

`signMessage` can come from a wallet adapter (`wallet.signMessage`) or, for tests:

```typescript theme={null}
import nacl from 'tweetnacl';

signMessage: async (msg) => nacl.sign.detached(msg, keypair.secretKey)
```

***

## Error Handling

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

try {
  const result = await attestedCompute(
    { lhsHandle, op: AttestedComputeSupportedOps.Gt, rhsPlaintext: 100n },
    { address: wallet.publicKey, signMessage: wallet.signMessage }
  );
} catch (error) {
  if (error instanceof AttestedComputeError) {
    console.error('Attested compute failed:', error.message);
  }
}
```

### Errors

| Error Message                                           | Cause                              | Solution                                            |
| ------------------------------------------------------- | ---------------------------------- | --------------------------------------------------- |
| `Invalid handle provided for attested compute`          | Empty or non-numeric handle        | Pass a decimal u128 handle string                   |
| `Unsupported operation for attested compute`            | Unknown `op`                       | Use a value from `AttestedComputeSupportedOps`      |
| `Wallet address is required for attested compute`       | Missing `options.address`          | Pass wallet public key                              |
| `signMessage function is required for attested compute` | Missing signer                     | Pass `wallet.signMessage`                           |
| `Covalidator API request failed: ...`                   | Network / auth / allowance failure | Ensure allowance exists; check covalidator response |
| `Covalidator returned empty result`                     | Malformed response                 | Retry; verify handle exists in covalidator store    |
| `Failed to create Ed25519 verification instruction`     | Bad signature payload              | Response may be corrupted                           |
| `Attested compute failed: ...`                          | General failure                    | Inspect `cause` / message details                   |

***

## Compute with Allowance Voucher / Session Key

Compute can be performed with a session key instead of the wallet using `attestedComputeWithVoucher()`:

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

const sessionKeypair = Keypair.generate();
const voucherWithSig = await grantSessionKeyAllowanceVoucher(
  { address: wallet.publicKey, signMessage: wallet.signMessage },
  sessionKeypair.publicKey,
  new Date(Date.now() + 60 * 60 * 1000)
);

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"
```

See [Allowance Voucher](/svm/js-sdk/voucher/allowance-voucher) for full details.

## When to Use Attested Compute

| Use Case                                                   | Use                                                           |
| ---------------------------------------------------------- | ------------------------------------------------------------- |
| Predicate without revealing the raw value (`score >= 700`) | **Attested Compute**                                          |
| On-chain gate based on that predicate                      | **Attested Compute** + Ed25519 IX                             |
| Show the actual decrypted number in a UI                   | [Attested Reveal](/svm/js-sdk/attestations/attested-reveal)   |
| Verify a full plaintext on-chain                           | [Attested Decrypt](/svm/js-sdk/attestations/attested-decrypt) |
| Decrypt/compute via a session key                          | [Allowance Voucher](/svm/js-sdk/voucher/allowance-voucher)    |
