# TEE Network

### Overview

Clique is pioneering a new paradigm for building dApps and consumer applications with our TEE Network, which you can think of as an off-chain AWS Lambda system. It offers confidentiality and verifiability for on-chain applications while being highly versatile, cost-effective, and secure.

Our network architecture is built on top of TEE nodes supporting custom bytecode execution for VMs (currently EVM and WASM, with more to come). We provide SDKs enabling clients to build custom executors in TEEs, make smart contract calls to the TEE network, and verify attestations and trusted signatures on-chain. Orchestration nodes within enclaves create compute graphs, distribute tasks, and aggregate proofs. We currently focus on Intel SGX, with plans to support AMD SEV-SNP, Intel TDX, and NVIDIA H100 soon, enhancing trust assumptions and efficiency.

### Use Cases

**TLS Oracle**

Access arbitrary off-chain TLS session data and integrate them with your smart contracts seamlessly. Our TEE executors support end-to-end encrypted private credential handling for such calls while making sure the entire session is notarized in a fully verifiable manner.

**Attestations**

Create on-chain attestations of your application's off-chain server execution results in a verifiable manner to create more interoperable smart contracts.&#x20;

#### Incentive Distribution & Loyalty Programs

Efficiently distribute incentives to valuable users in a fully verifiable manner composing both on-chain and off-chain data. Create callbacks/hooks for embedded loyalty programs with fee rebates in your smart contracts.

#### Off-Chain Central Limit Order Books (CLOBs)

Enabling secure and efficient order matching and trade execution without the need for every operation to be recorded on-chain, thereby significantly reducing transaction costs and latency. Trades can be batch-verified through TEE's.

#### Example Integrations

* **Optimism**: Partnered with 20+ DeFi protocols (e.g., Aave, Synthetix, Across, Velodrome) for on-chain data attestations and off-chain social data, incentivizing over $500M in DeFi volume on OP.
* **Arbitrum**: Worked with 25+ top ARB games (e.g., Pirate Nations, Dininho) to attest off-chain gameplay data on-chain for cross-game incentive distribution and token emissions.
* **Linea**: Incentivized over 10k users to attest social data on-chain through our TEE oracles for Sybil resistance.
* **Ronin**: Enabled over 5k users to attest their Steam play history data on-chain through our TEE oracles for incentive distribution by Ronin games.

### Features

* Secure, efficient, and verifiable off-chain computation. Arbitrary compute with server-like performance and integrity guarantees.
* Support for TLS calls to obtain external data. Query or expose HTTPS endpoints/APIs with data confidentiality.
* Running off-chain app components in TEEs for verifiable and attestable results on-chain.
* Verifiable AI model outputs.
* User data attestation for efficient incentive distribution.
* Social verification and login.
* MEV strategies/relay, automation bots, AI training/inference.
* Use cases akin to zkVMs (loyalty points, rebates, DeFi risk assessment), gaming servers, and decentralized frontends/gateways.
* Implementing coordination strategies between untrusting parties.
* Securing wallets, bridges, and oracles with TEEs, with validator signing keys secured using HSMs.

### Security Practices

* Verifiable on-chain TEE attestation with attested signatures on the side.
* Response time guarantees with a network of TEE nodes. Liveness guarantees further down the line with crypto-economic mechanisms.
* Persistent storage of encrypted state and key-sharing methodologies through native sealing.
* TEE committees using Intel SGX/TDX, AWS Nitro, AMD SEV-SNP, etc.
* Utilization of Oblivious RAM (ORAM) for enhanced privacy w\.r.t access patterns.
* Utilization of community-audited DCAP to mitigate lately discovered side channels.&#x20;


# Compute Coordination Network

We plan to support multiple proof types through a generalized **compute coordination layer** in the future for off-chain verifiable compute requests. This basically enables smart contracts (and even general applications!) to access and utilize verifiable computing resources, such as Clique's TEE network.&#x20;

At the core of this offering is an **auction-based system**, engineered to optimize the distribution of computational services. This system carefully assesses the needs of diverse applications, from blockchain-based smart contracts to conventional cloud-based services, and methodically pairs them with the most suitable compute providers. The service places significant emphasis on aligning application requirements with the most relevant computational offerings, enhancing this match with game-theoretic mechanisms that drive an efficient and transparent auction process.


# Clique Application Structure

Clique provides an official task registry for the community to download, publish, build, and share tasks. You can easily submit a query composed of these tasks through our config file [Clique Manifest](/references/clique-manifest). You can also deploy custom tasks yourself if there is no existing task that fits your needs.

### Task Deployment

You can deploy a custom task by:

* Initialize a custom task template through [Clique CLI](/build-with-clique/clique-cli)
* Customize your task code and update your task manifest
* Verify the manifest and submit it to the Clique TEE Network through [Clique CLI](/build-with-clique/clique-cli)

Here is a simple generated task manifest

```toml
spec-version = "1"
name = "clique_fibonacci"
type = "Dynamic"

proof-type = ["TEE"]

[input]
n = { type = "u256", description = "n" }

[output]
result = { type = "u256", description = "fibonacci sequence for n" }

[code]
type = "EVM"
data = "6080604052348015600e575f80fd5b5061022d8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063371432331461002d575b5f80fd5b610047600480360381019061004291906100fd565b61005d565b6040516100549190610137565b60405180910390f35b5f80820361006d575f90506100c1565b6001820361007e57600190506100c1565b5f80600190505f80600290505b8581116100b957828461009e919061017d565b915082935081925080806100b1906101b0565b91505061008b565b508093505050505b919050565b5f80fd5b5f819050919050565b6100dc816100ca565b81146100e6575f80fd5b50565b5f813590506100f7816100d3565b92915050565b5f60208284031215610112576101116100c6565b5b5f61011f848285016100e9565b91505092915050565b610131816100ca565b82525050565b5f60208201905061014a5f830184610128565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610187826100ca565b9150610192836100ca565b92508282019050808211156101aa576101a9610150565b5b92915050565b5f6101ba826100ca565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036101ec576101eb610150565b5b60018201905091905056fea2646970667358221220365d9643fc7bf275e8e02fe7cd0f5a26ff14400be75bed36b39c21b2dd78440964736f6c634300081a0033"
abi = '[{"inputs":[{"internalType":"uint256","name":"n","type":"uint256"}],"name":"evaluate","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"pure","type":"function"}]'
```

The EVM template for the custom task is available on GitHub at

<https://github.com/CliqueOfficial/template-evm>

### Clique Integration Flow

#### On-chain Application

Here is a diagram that describes how the Clique Network can be integrated with your DApp.

<figure><img src="/files/RrXH2hBTawHiCNL81LuN" alt=""><figcaption><p>Smart Contract Integration with the Clique Network</p></figcaption></figure>

**Step-by-Step Integration Flow**

1. Register a callback by using our [Smart Contract SDK](/build-with-clique/smart-contract-sdk)
2. Once the response is fulfilled and verified by the `CliqueTaskManager` contract, it will invoke a callback registration.&#x20;

#### Off-chain Application

You can check out our [Clique Client SDK](/build-with-clique/clique-client-sdk) to integrate with your off-chain service. Here are integration examples for a few different languages:

* \[Rust example link]
* \[NodeJS example link]
* \[Web example link]


# Clique CLI

The Clique Command Line Interface (Clique CLI) is an open-source tool that enables you to develop, build, test, and deploy your tasks to the Clique Network.&#x20;


# Installation

### Get Pre-built Executable from Cargo (Recommended)

If you have installed the Rust toolchain already, you can get our pre-built executable from cargo.

```bash
$ cargo install clique-cli
```

### Build from Source

You can also build the executable yourself with the following guidelines.

#### Pre-requisites

* [Rust-toolchain ](https://rust-lang.github.io/rustup/concepts/channels.html)

#### Step-by-step Guide

**Clone the Clique CLI from GitHub**&#x20;

```bash
$ git clone https://github.com/CliqueOfficial/clique-protocol-sdk.git
```

**Build the Binary with Cargo**

```bash
$ cd cli
$ cargo build --release --bin clique
```

**Install the Built Executable to System**

```bash
# Install the binary locally (recommended)
$ cp target/release/clique ~/.local/bin/
# Or if you want to install it globally
$ sudo cp target/release/clique /usr/bin/
```

{% hint style="info" %}
Make sure `~/.local/bin` is includes in `$PATH` environment variable.
{% endhint %}


# Develop Task

### Initialize from Template

To initialize a repository, use the following command:

<pre class="language-bash"><code class="lang-bash"><strong>$ clique init --template evm
</strong></code></pre>

This command will utilize the [EVM template](https://github.com/CliqueOfficial/template-evm) to create a new project, including contract code and a corresbonding Clique Task Manifest file. Here, "evm" specifies the use of the EVM template. During the subsequent build task phase, the contract code will be compiled to generate EVM bytecode, which will then be populated into the Manifest file (note that the bytecode format is different based on the VM you specify -- we plan to support WASM, RISC V, etc in the future).

### How to Use

Before initialization, it is essential to establish an **empty** directory to serve as your workspace.

<pre class="language-bash"><code class="lang-bash"><strong>$ mkdir workspace
</strong><strong>$ cd workspace
</strong>$ clique init --template evm
</code></pre>

### Project Structure

After initialization, the project structure is as follows:

```
/workspace
-- contracts
   -- Main.sol
-- manifest.toml
-- foundry.toml
```

* `/contracts/Main.sol` is the primary Solidity smart contract source file. This file contains the core smart contract logic and functionalities within the project.
* `manifest.toml` is a clique task metadata written in  TOML, including I/O schemas, proof types, and optional code or task sections depending on the task type. For more detailed information, please refer to [Clique Manifest](/references/clique-manifest)
* `foundry.toml` is a configuration file specific to the [Foundry ](https://getfoundry.sh/)toolkit. You can use Foundry to compile and test your contracts. Foundry will also be required for the subsequent build phase to compile the contracts.

If you haven't set up the Foundry environment yet, run the following command in your terminal, then follow the onscreen instructions:

```
curl -L https://foundry.paradigm.xyz | bash
```

### Develop Task

Upon completion of template initialization, you can modify the contract and `manifest.toml`.

It is important to note that the contract entry point is fixed and must be `Main.sol`. Users can import other contracts into `Main.sol`.&#x20;

After modifying the contracts, users should update `manifest.toml` with new `name`, `input` and `output`  sections according to the changes made to the contracts. The `code` section should be left empty, as it will be automatically populated by the CLI during build stage.


# Build Task

Run the following command to build the developed task.

```bash
clique build --type evm
```

By specifying "evm", the build process is set to generate EVM bytecode. Future updates will introduce support for other bytecode formats, such as WASM.

After build, your workspace structure should look like the following:

```
/workspace
-- contracts
   -- Main.sol
-- tasks
   -- manifest.toml
-- manifest.toml
-- foundry.toml
```

During the development phase, the developer has modified the contract code and `manifest.toml` , with the `code` section in `manifest.toml` left blank.&#x20;

In the build phase, we will generate a copy of `manifest.toml` to `tasks/manifest.toml` and automatically populate the `code` section. We utilize the Foundry toolkit to compile the contracts and automatically populate the compiled bytecode into the newly copied `manifest.toml`.


# Test Task

To test the task without publishing, run the following command:

```
$ clique test -f manifest.toml
```


# Deploy Task

To deploy the task locally, run the following command.

```bash
clique deploy --kernel http://127.0.0.1:8000
```

To publish the task to the Clique network,

```
clique deploy --kernel http://kernel-testnet.clique.tech
```

This command will default to deploying the `tasks/manifest.toml` file.


# Clique Client SDK

{% hint style="info" %}
This section primarily focuses on integrating the off-chain component of your application with the Clique co-processor. For on-chain integration, refer to[Smart Contract SDK](/build-with-clique/smart-contract-sdk)
{% endhint %}

The Clique Client SDK is an open-source library that enables users to interact with the Clique Network.  We currently support Rust, NodeJS, and Web.

* [Rust SDK](https://github.com/CliqueOfficial/clique-protocol-sdk/tree/main/clique-client-sdk)
* [NodeJS SDK](https://www.npmjs.com/package/@cliqueofficial/clique-client-sdk-node)
* [Web SDK](https://www.npmjs.com/package/@cliqueofficial/clique-client-sdk-web)

The SDK facilitates communication between your application clients and the Clique Network. Custom client implementation is also possible. The flowchart below depicts a simple communication process.

<figure><img src="/files/XqxBaRGCrE0TswVLqS8L" alt=""><figcaption></figcaption></figure>

The client SDK executes two primary steps that are outlined in subsequent sections:&#x20;

1. Forward the query and poll results from the network: [Clique Query](/references/clique-query)
2. Verify the proof upon receiving the response

### Proof Verification

{% hint style="info" %}
The verification process is automatically handled if you're using the Clique Client SDK.
{% endhint %}

The proofs of each task are aggregated in an aggregation program that runs in our TEE kernel. Roughly, each executor provides a proof (eg. TEE attestation or trusted signatures) for their respective programs. The kernel then aggregates these proofs in its own TEE and produces a remote attestation of the execution results.

To fully understand the verification process, please refer to the official [Intel SGX Remote Attestation Docs](https://www.intel.com/content/www/us/en/developer/tools/software-guard-extensions/attestation-services.html) here.

### Rust SDK

#### How to Use

Add this dependency to your `Cargo.toml`

```toml
clique-client-sdk = { git = "https://github.com/CliqueOfficial/clique-protocol-sdk" }
serde_json = { version = "1.0", features = ["preserve_order"] }
tokio = { version = "1.38.0", features = ["full"] }
```

Here is an example:

```rust
use std::time::Duration;

use clique_client_sdk::CliqueClient;
use serde_json::json;

#[tokio::main]
async fn main() {
    // The endpoint for the Clique Network
    let endpoint = "https://localhost:8000";
    // Interval for polling the Clique Network to retrieve results
    let polling_interval = Duration::from_millis(500);
    // Maximum number of retries for network errors
    let retry_num = 5;
    // If the user creates a query with the same id, method, and params, 
    // the client will return the result of the existing query when the value is true;
    // otherwise, the client will throw an exception.
    let allow_exist_query = false;
    // Trusted mr_enclaves of clique-kernel
    let trusted_enclaves = Some(vec![
        "5d474d0e8b431764ddf3db67b1028399d42301340ceb4abc840c4dee426e0d9d".to_string(),
    ]);
    // Trusted mr_signers of clique-kernel
    let trusted_signers = Some(vec![
        "6601c448087c060907a3c71f1c10fbae92260bef8ac37258b2314338042dadb4".to_string(),
    ]);

    // Create a CliqueClient with custom configuration for polling interval, retry limit, allow_exist_query, trusted_enclaves, trusted_signers
    let client = CliqueClient::with_config(
        endpoint,
        polling_interval,
        retry_num,
        allow_exist_query,
        trusted_enclaves,
        trusted_signers,
    )
    .unwrap();

    // Alternatively, create a CliqueClient with default configuration
    let _client = CliqueClient::new(endpoint, trusted_enclaves, trusted_signers).unwrap();

    // Create a single query using `serde_json::json`
    let json_query = json!({
        "id": 1,
        "method": "clique_fibonacci",
        "params": {"n": "10"},
        "input_types": {"n": "u256"},
        "custom_types": {}
    });

    // Run the query and wait for the result
    let result = client.run_query(json_query).await.unwrap();
    println!("result: {:?}", result);

    // Create batch query using `serde_json::json`
    let json_query = json!([
        {"id": 2, "method": "clique_fibonacci", "params": {"n": "11"}, "input_types": {"n": "u256"}, "custom_types": {}},
        {"id": 3, "method": "clique_fibonacci", "params": {"n": "12"}, "input_types": {"n": "u256"}, "custom_types": {}}
    ]);

    // Run the query and wait for the result
    let result = client.run_query(json_query).await.unwrap();
    println!("result: {:?}", result);
}
```

### NodeJS SDK

#### How to Use

Add this dependency to your `package.json`:

```sh
pnpm add @cliqueofficial/clique-client-sdk-node
# OR
yarn add @cliqueofficial/clique-client-sdk-node
# OR 
npm install @cliqueofficial/clique-client-sdk-node 
```

Here is an example:

```javascript
const { Client } = require('@cliqueofficial/clique-client-sdk-node');

(async () => {
  const client = new Client({ 
    endpoint: 'http://localhost:8000', 
    pollingInterval: 20, // default value is 20 ms
    retryNumber: 5,  // default value is 5
    allowExistQuery: false, // default value is false. If the user creates a query with the same id, method, and params, the client will return the result of the existing query when the value is true; otherwise, the client will throw an exception.
    trustedEnclaves: ['5d474d0e8b431764ddf3db67b1028399d42301340ceb4abc840c4dee426e0d9d'], // default is undefined. Trusted mr_enclaves of clique-kernel, if the value is undefined, all mr_enclaves will be trusted.
    trustedSigners: ['6601c448087c060907a3c71f1c10fbae92260bef8ac37258b2314338042dadb4'], // default is undefined. Trusted mr_signers of clique-kernel, if the value is undefined, all mr_signers will be trusted.
  });

  // Create single query
  const query = {
    id: 1,
    method: 'clique_fibonacci',
    params: { n: '10' },
    inputTypes: { n: 'u256' },
  };
  // OR batch query
  const query = [
    {
      id: 2,
      method: 'clique_fibonacci',
      params: { n: '11' },
      inputTypes: { n: 'u256' },
    },
    {
      id: 3,
      method: 'clique_fibonacci',
      params: { n: '12' },
      inputTypes: { n: 'u256' },
    },
  ];

  // Run the query and wait for the result
  const response = await client.runQuery(query);
  console.log("runQuery response:", response);
})();
```

### Web SDK

Add this dependency to your `package.json`:

```sh
pnpm add @cliqueofficial/clique-client-sdk-web
# OR
yarn add @cliqueofficial/clique-client-sdk-web
# OR 
npm install @cliqueofficial/clique-client-sdk-web
```

Here is an example:

```javascript
import { Client } from '@cliqueofficial/clique-client-sdk-web';

const client = new Client({ 
  endpoint: 'http://localhost:8000', 
  pollingInterval: 20, // default value is 20 ms
  retryNumber: 5,  // default value is 5
  allowExistQuery: false, // default value is false. If the user creates a query with the same id, method, and params, the client will return the result of the existing query when the value is true; otherwise, the client will throw an exception.
  trustedEnclaves: ['5d474d0e8b431764ddf3db67b1028399d42301340ceb4abc840c4dee426e0d9d'], // default is undefined. Trusted mr_enclaves of clique-kernel, if the value is undefined, all mr_enclaves will be trusted.
  trustedSigners: ['6601c448087c060907a3c71f1c10fbae92260bef8ac37258b2314338042dadb4'], // default is undefined. Trusted mr_signers of clique-kernel, if the value is undefined, all mr_signers will be trusted.
});

// Create single query
const query = {
  id: 1,
  method: 'clique_fibonacci',
  params: { n: '10' },
  inputTypes: { n: 'u256' },
};
// OR batch query
const query = [
  {
    id: 2,
    method: 'clique_fibonacci',
    params: { n: '11' },
    inputTypes: { n: 'u256' },
  },
  {
    id: 3,
    method: 'clique_fibonacci',
    params: { n: '12' },
    inputTypes: { n: 'u256' },
  },
];

// Run the query and wait for the result
const response = await client.runQuery(query);
console.log("runQuery response:", response);

// OR run the query with encryption enabled and wait for the result
const response = await client.runEncryptedQuery(query);
console.log("runEncryptedQuery response:", response);
```


# Smart Contract SDK

The Clique Smart Contract SDK offers a set of interfaces and types for interacting with the Clique Network through on-chain smart contracts.

### Get Started

The SDK source code can be found [here on GitHub](https://github.com/CliqueOfficial/clique-avs-intergration).&#x20;

### Foundry

```
forge install CliqueOfficial/clique-contracts
```


# Smart Contract Integration

This overview explains how Clique can be integrated with your smart contracts.

### Example

{% code lineNumbers="true" %}

```solidity
/// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {ICliqueTaskManger} from "clique-contracts/ICliqueTaskManger.sol";

struct Response {
    bytes16 data;
}

struct EchoParams {
    bytes data;
}

contract MockClient {
    address public immutable _manager;

    event CallbackInvoked();

    constructor(address manager) {
        _manager = manager;
    }

    function callback(bytes calldata _response) external {
        Response memory response = abi.decode(_response, (Response));
        require(response.data == bytes16("hello, clique"), "Invalid response");
        emit CallbackInvoked();
    }

    function run() public {
        ICliqueTaskManager.Task memory task = ICliqueTaskManager.Task(
            0,
            "echo",
            abi.encode(EchoParams("hello, clique"))
        );
        ICliqueTaskManager(_manager).createNewTask{value: 0.05 ether}(
            abi.encode(task),
            this.callback.selector
        );
    }
}
```

{% endcode %}

Let's break down the example.

```solidity
import {ICliqueTaskManger} from "clique-contracts/ICliqueTaskManger.sol";
```

Import the Clique Contract SDK here.

`run()` is the entry point where we initialize a query struct and call the `createNewTask` function with a callback selector:

```solidity
function run() public {
    ICliqueTaskManager.Task memory task = ICliqueTaskManager.Task(
        0,
        "echo",
        abi.encode(EchoParams("hello, clique"))
    );
    ICliqueTaskManager(_manager).createNewTask{value: 0.05 ether}(
        abi.encode(task),
        this.callback.selector
    );
}
```

Once the task is fulfilled, `callback`will be invoked with response bytes. Program execution resumes afterward.

```solidity
function callback(bytes calldata _response) external {
    Response memory response = abi.decode(_response, (Response));
    require(response.data == bytes16("hello, clique"), "Invalid response");
    emit CallbackInvoked();
}
```

{% hint style="info" %}
Asynchronous programming in Solidity
{% endhint %}

### On-Chain Verification

{% hint style="info" %}
For details on the standard verification process, refer to the [Verification](/references/verification) section. This process mirrors the one used during setup. To minimize gas costs, subsequent verifications employ an ECDSA-based solution, as outlined in this section.
{% endhint %}

To use ECDSA-based verification, `CliqueTaskManager` maintains a trusted public key. And a **Trust Setup** process is required when a kernel initially fulfills tasks. It must submit a triple tuple consisting of a response, attestation, and signature.  If the attestation is valid, the public key recovered from this `signature, CUID` pair will be trusted. The ephemeral key must be regenerated each time the kernel restarts. Once **Trust Setup** done, the `attestation` could be empty when the kernel fulfills subsequent tasks.&#x20;

For more information, please refer to [Verification](/references/verification#on-chain-verification).


# Clique Official Tasks

Currently, Clique has built-in some official tasks, including:

* Social Verification Tasks, see more details in [Social Verification](/sample-task-tutorials/social-verification)
* TLS Calls Task, see more details in [Making Arbitrary TLS Calls (TLS Oracle)](/sample-task-tutorials/making-arbitrary-tls-calls-tls-oracle)

In addition to built-in tasks, Clique also offers [Clique Attestation SDK](/toolchain/clique-attestation-sdk) for creating on-chain attestations for arbitrary on-chain and off-chain data.&#x20;


# Clique Manifest

The Clique Manifest details the metadata for each task including I/O schemas, proof types, and optional `[code]`or`[tasks]` sections.&#x20;

The manifest itself is written in TOML. If you are not familiar with it, you can review [this cheatsheet](https://quickref.me/toml.html) in 5 minutes.

### Phantom and Non-Phantom task

The primary distinction between these two types lies in whether the task is dispatched to an executor.

**Phantom tasks** do not involve execution logic; instead, they focus on transforming arguments that explain how values are passed between tasks.  Only **Schema** is considered a phantom task for now.&#x20;

Here is an example manifest of a phantom task:

```toml
spec-version = "1"
name = "yourOrganization_customRequest"
type = "Schema"

proof-type = ["TEE"]

[types.Transformation]
from = { type = "string", description = "json pointer to field in response" }
soltype = { type = "string", description = "solidity type" }

[input]
url = { type = "string", description = "Request url" }
encoding = { type = "Transformation[]", description = "encoding format" }

[output]
response = { ref = "$tasks.clique_httpsRequest.response" }

[[tasks]]
name = "clique_httpsRequest"
proof-preference = "TEE"
[tasks.input]
url = "$input.url"
encoding = "$input.encoding"
```

**Non-Phantom** tasks include `Dynamic` and `BuiltIn` tasks. `BuiltIn`tasks are maintained by Clique and are currently restricted for other developers. `Dynamic` tasks, on the other hand, can be built by anyone with the correpsponding `evm` or `wasm` bytecode sent to executors in the Clique Network for computation and proof generation. Each `Dynamic`task must contain a `[code]` section.&#x20;

### Value Types

In version 1 of the TOML manifest, the following types are supported:

* `bool`
* `string`
* `bytes`
* `address`
* `float`
* `i8`, `i16`, `i32`, `i64`, `i128`, `i256`
* `u8`, `u16`, `u32`, `u64`, `u128`, `u256`
* `{type}[]`
  * The **array** type, for example, an array of `string`, is denoted as`string[]`.
* custom type

#### Custom Type

In addition to the basic types, you can add a `[types]` section to define custom types, specifying the structure of your custom types within it. Currently, custom types only support the use of basic types and do not allow for nested custom types.

For instance, if you wish to add a custom type named `Transformation` with two fields of type `string`, you would do the following:

```
[types.Transformation]
from = { type = "string", description = "json pointer to field in response" }
soltype = { type = "string", description = "solidity type" }
```

Then, you can incorporate your custom type in the `[Input]` or `[Output]` sections of your manifest:

```
[input]
field1 = { type = "Transformation", description = "single custom type" }
field2 = { type = "Transformation[]", description = "an array of the custom type" }
```

#### Type Mapping

Here is the mapping correspondence between our clique value types and JSON types, Solidity types, as well as Rust types:

| Clique types | Json types                | Solidity types  | Rust types                    |
| ------------ | ------------------------- | --------------- | ----------------------------- |
| `bool`       | bool                      | bool            | bool                          |
| `string`     | string                    | string          | String                        |
| `bytes`      | hex string with 0x prefix | bytes           | Vec\<u8>                      |
| `address`    | hex string with 0x prefix | address         | clique\_types::value::Address |
| `{type}[]`   | array                     | array           | Vec\<type>                    |
| `float`      | number                    | *Not Supported* | f64                           |
| `i8`         | number                    | int8            | i8                            |
| `i16`        | number                    | int16           | i16                           |
| `i32`        | number                    | int32           | i32                           |
| `i64`        | number                    | int64           | i64                           |
| `i128`       | decimal string            | int128          | i128                          |
| `i256`       | decimal string            | int256          | clique\_types::value::Int256  |
| `u8`         | number                    | uint8           | u8                            |
| `u16`        | number                    | uint16          | u16                           |
| `u32`        | number                    | uint32          | u32                           |
| `u64`        | number                    | uint64          | u64                           |
| `u128`       | decimal string            | uint128         | u128                          |
| `u256`       | decimal string            | uint256         | clique\_types::value::Uint256 |
| custom type  | object                    | struct          | struct                        |

### Built-In variables

#### `$input`

* The task input object

#### `$tasks`

* The output of each dependency task. You can reference a task output by its `id`. &#x20;

### Manifest Structure

**`name`**&#x20;

* **Type**: `string`
* Unique identifier for each task in the Clique Network, The recommended format is `{yourNamespace}_{taskName}`.&#x20;

**`spec-version`**&#x20;

* **Type**: `"1"`
* This refers to the spec version of this manifest file, which should be fixed as `"1"` for now.

**`type`**

* **Type**: `"Schema" | "Dynamic" | "BuiltIn"`
* This refers to the task type. See the [Phantom and Non-Phantom ](#phantom-and-non-phantom-task)section for details. The`BuiltIn` task format is only used by Clique right now to publish official tasks, so you should specify `Dynamic` here.

**`proof-type`**

* **Type**:  `array`
* This refers to the supported proof type for this task. Currently, only the `"TEE"` proof type is supported.

**`input`**

* **Type**: `table`
* This describes the required arguments for this particular task. `input` will be validated before the task is actually dispatched to an executor.

**`input.{field}.type`**

* **Type**: `string`
* This refers to the value type of this field.&#x20;

**`input.{filed}.description`**

* **Type**: `string`
* Field description. Optional.

**`output`**

* **Type:** `object`
* The data structure returned by this task.

**`output.{filed}.type`**

* Value type. Required if it's a non-phantom task.

**`output.{field}.description`**

* Field description. Optional.

**`output.{field}.ref`**

* **Type**: reference string
* Reference to other field. Required for `Schema` task. If the `ref` is specified, refrain from setting the `type` as the `ref` inherently determines the `type`.

**`tasks`**

* **Type**: `array`
* Dependencies. Required for `Schema` task.

**`[[tasks.id]]`**

* **Type**: `string`
* The unique id of its dependencies. Use `[[tasks.name]]` by default if it's empty.

**`[[tasks.name]]`**

* **Type:** `string`
* Name of dependent task.

**`[[tasks.proof-perference]]`**

* **Type**: `"TEE"`
* This refers to the preferred proof type for the task, which must be one of the proof types supported by the task.

**`[[tasks.input]]`**

* **Type**: `table`
* Transformation of input or output from others to required parameters.

**`[code.type]`**

* **Type: `"EVM" | "WASM"`**
* Specify the type of bytecode.

**`[code.data]`**

* **Type**: `string`
* This current supports two types of values depending on the VM that's used
  * evm: Hex-encoded bytecode for evm
  * wasm: Hex-encoded bytecode for WAT or WASM&#x20;

**`[code.abi]`**

* **Type**: `string`
* This is the ABI of the entry point function. Currently it's EVM only.

**`types`**

* **Type**: `table`
* This refers to the custom types.

**`types.{custom-type-name}.{field}.type`**

* **Type**: `string`
* This refers to the value type of this field.&#x20;

**`types.{custom-type-name}.{field}.description`**

* **Type**: `string`
* Field description. Optional.

### Examples

Here is an exmaple of `Dynamic EVM` task:

```toml
spec-version = "1"
name = "yourOrganization_dynamicTask"
type = "Dynamic"

proof-type = ["TEE"]

[types.MyCustomType]
price = { type = "u64", description = "product price" }
name = { type = "string", description = "product name" }

[input]
boolInput = { type = "bool", description = "bool" }
stringInput = { type = "string", description = "string" }
bytesInput = { type = "bytes", description = "bytes" }
addressInput = { type = "address", description = "address" }
floatInput = { type = "float", description = "float number" }
i8NumberInput = { type = "i8", description = "description is optional" }
u8NumberInput = { type = "u8" }
i16NumberInput = { type = "i16" }
u16NumberInput = { type = "u16" }
i32NumberInput = { type = "i32" }
u32NumberInput = { type = "u32" }
i64NumberInput = { type = "i64" }
u64NumberInput = { type = "u64" }
i128NumberInput = { type = "i128" }
u128NumberInput = { type = "u128" }
i256NumberInput = { type = "i256" }
u256NumberInput = { type = "u256" }
arrayInput = { type = "i64[]", description = "i64 array" }
strArrayInput = { type = "string[]", description = "string array" }
customArrayInput = { type = "MyCustomType[]", description = "custom type array" }
customInput = { type = "MyCustomType", description = "single custom type" }

[output]
numberOutput = { type = "i256", description = "i256 number" }

[code]
type = "EVM"
data = "6080604052348015600f57600..."
abi = '[{"type":"function","name":"evaluate","inputs":...,"outputs":..., ...}]'
```

Here is an exmaple of `Dynamic WASM` task:

<https://github.com/CliqueOfficial/template-wasm>&#x20;

{% hint style="info" %}
WASM does not support address, i256 or u256.
{% endhint %}


# Clique Query

Clique supports JSON-RPC-styled queries.&#x20;

<table><thead><tr><th width="188">Field</th><th width="270">description</th><th>required</th></tr></thead><tbody><tr><td>id</td><td>Unique query ID</td><td>Yes</td></tr><tr><td>method</td><td>Task name</td><td>Yes</td></tr><tr><td>params</td><td>Task input</td><td>Yes</td></tr><tr><td>input_types</td><td>Task input types</td><td>Only required by Clique Client SDK</td></tr><tr><td>custom_types</td><td>Custom types used in task input types</td><td>Only required by Clique Client SDK</td></tr></tbody></table>

Clique Network supports both on-chain and off-chain queries. Although they both follow our JSON-RPC-styled queries, the specific types naturally differ due to the different programming languages.

{% hint style="warning" %}
Note that you cannot create an identical Clique Query. If you attempt to create an identical Clique Query, you will encounter a `QueryAlreadyExists` error. If you do not need to rerun the Clique Query, you can simply retrieve the previous results instead of creating the same query again. If you indeed wish to rerun the query, specify a different `id` to create a new query.
{% endhint %}

### On-Chain Query

For example, this is the manifest file for the `clique_fibonacci` sample task:

```toml
spec-version = "1"
name = "clique_fibonacci"
type = "Dynamic"

proof-type = ["TEE"]

[input]
n = { type = "u256", description = "n" }

[output]
result = { type = "u256", description = "fibonacci sequence for n" }
```

To create a query for running the `clique_fibonacci` task, you can define the task input using a struct, such as `Params`, and construct the query via `ICliqueTaskManager.Task`:

```solidity
import {ICliqueTaskManager} from "clique-contracts/ICliqueTaskManager.sol";

struct Params {
    uint256 n;
}

contract MyContract {
    function run(uint256 n) public {
        uint32 id = 0;
        bytes memory method = "clique_fibonacci";
        Params memory params = Params(n);
        
        ICliqueTaskManager.Task memory task = ICliqueTaskManager.Task(
            id,
            method,
            abi.encode(params)
        );
        
        // use ICliqueTaskManager to create new query
        // ...
    }
}
```

The above example is quite straightforward. Next, we will demonstrate a slightly more complex example. Below is the manifest file for our `clique_httpsRequest` task, which can be used to provide TLS calls for smart contracts:

```toml
spec-version = "1"
name = "clique_httpsRequest"
type = "BuiltIn"

proof-type = ["TEE"]

[types.Transformation]
from = { type = "string", description = "json pointer to field in response" }
soltype = { type = "string", description = "solidity type" }

[input]
url = { type = "string", description = "Request url" }
encoding = { type = "Transformation[]", description = "encoding format" }

[output]
response = { type = "bytes", description = "ABI encoded" }
```

Note that this task includes a custom type `Transformation`. Next, we will demonstrate how to create a query for this task:

```solidity
import {ICliqueTaskManager} from "clique-contracts/ICliqueTaskManager.sol";

struct Transformation {
    string from;
    string soltype;
}

struct Params {
    string url;
    Transformation[] encoding;
}

contract MyContract {
    function run() public {
        Transformation[] memory transformations = new Transformation[](2);
        transformations[0] = Transformation({from: "/0/id", soltype: "int16"});
        transformations[1] = Transformation({from: "/0/name", soltype: "string"});

        uint32 id = 0;
        bytes memory method = "clique_httpsRequest";
        Params memory params = Params({
            url: "https://jsonplaceholder.typicode.com/users",
            encoding: transformations
        });
        
        ICliqueTaskManager.Task memory task = ICliqueTaskManager.Task(
            id,
            method,
            abi.encode(params)
        );
        
        // use ICliqueTaskManager to create new query
        // ...
    }
}
```

For further details, please refer to [Smart Contract Integration](/build-with-clique/smart-contract-sdk/smart-contract-integration).

### Off-Chain Query

For off-chain tasks, we use JSON format to create queries. Users can create queries via the [Clique Client SDK](/build-with-clique/clique-client-sdk), or you can directly access the Clique Network to create queries. However, we strongly recommend using the Clique Client SDK, as it helps you validate the query, eliminating the need for you to manually perform complex validation.

Creating off-chain queries is straightforward and supports the creation of batch queries.

#### Single Query

If use our [Clique Client SDK](/build-with-clique/clique-client-sdk), here we use the Rust SDK as an example:

```rust
use serde_json::json;

// Create a single query for running clique_fibonacci task
let json_query = json!({
    "id": 1,
    "method": "clique_fibonacci",
    "params": {"n": "10"}
    "input_types": {"n": "u256"},
    "custom_types": {}
});


// Create a single query for running clique_httpsRequest task
let url = "https://jsonplaceholder.typicode.com/users";
let encoding = json!([
    {"from": "/0/id", "soltype": "int16"},
    {"from": "/0/name", "soltype": "string"},
]);
let json_query = json!({
    "id": 1,
    "method": "clique_httpsRequest",
    "params": {"url": url, "encoding": encoding },
    "input_types": {"url": "string", "encoding": "Transformation[]"},
    "custom_types": {"Transformation": {"from": "string", "soltype": "string"}}
});
```

{% hint style="info" %}
When using the Clique Client SDK, you need to specify `input_types` and `custom_types`. These type information must be filled according to the `input` section of the task's manifest and will be used by the client SDK to validate the query.
{% endhint %}

If you wish to directly access the Clique Network, you can construct the JSON query in the following format, but you will be responsible for validating the entire process yourself:

```json
// JSON query for clique_fibonacci task
{
    "id": 1, 
    "method": "clique_fibonacci", 
    "params": {"n": "10"}
}

// JSON query for clique_httpsRequest task
{
    "id": 1,
    "method": "clique_httpsRequest",
    "params": {
        "url": "https://jsonplaceholder.typicode.com/users", 
        "encoding": [
            {"from": "/0/id", "soltype": "int16"},
            {"from": "/0/name", "soltype": "string"},
        ]
    },
}
```

#### Batch Query

If use our [Clique Client SDK](/build-with-clique/clique-client-sdk):&#x20;

```rust
use serde_json::json;

// Create batch query
let json_query = json!([
    {"id": 2, "method": "clique_fibonacci", "params": {"n": "10"}, "input_types": {"n": "u256"}, "custom_types": {}},
    {"id": 3, "method": "clique_fibonacci", "params": {"n": "11"}, "input_types": {"n": "u256"}, "custom_types": {}},
    {"id": 4, "method": "clique_fibonacci", "params": {"n": "12"}, "input_types": {"n": "u256"}, "custom_types": {}}
]);
```

If accessing the Clique Network directly:

```json
[
    {"id": 2, "method": "clique_fibonacci", "params": {"n": "10"}},
    {"id": 3, "method": "clique_fibonacci", "params": {"n": "11"}},
    {"id": 4, "method": "clique_fibonacci", "params": {"n": "12"}}
]
```


# Verification

### Minimal Trust Setup

Clique provides full verifiable process with minimal trust setup. For example, if you want to get twitter information for a user, all you need to trust is Twitter Official API. The rest parts of the whole process are fully secure and verifiable.

### Verification Mechanism

An execution DAG will be created when our kernel receives a query. The executor should generate corresponding proof along with the result and then the kernel will migrate to next state if proof validation passed.&#x20;

Here are the pseudocode of validation process for each kind

&#x20;**TEE Attestation**

{% hint style="info" %}
`codeHash` is the one of Clique Official TEE Executor by default.
{% endhint %}

```
BEGIN
 user_report := keccak(task_cuid, task_result)
 code_hash := codeHash in proof-perference
 RETURN verify_dcap_attestation(proof, user_report, code_hash)
END
```

**Signature**

{% hint style="info" %}
The signature is on the k256 curve.
{% endhint %}

```
BEGIN
    msg_hash := keccak(task_cuid, task_result)
    recovered_pk := ecrecover(proof, msg_hash)
    IF use public key THEN
        RETURN IS_EQUAL(recovered_pk, publicKey in proof-perference)
    ELSE IF use address THEN
        RETURN IS_EQUAL(pk_to_addr(recovered_pk), address in proof-perference)
    END
END
```

### Example

Let's take an example:

**Example Manifest**

```toml
name = "clique_example"
spec-version = "1"
type = "Schema"

proof-type = ["TEE"]

[input]
x = { type="u64", description="Example params x" }
y = { type="u64", description="Example params y" }

[output]
outputA = { ref = "$tasks.A.data" }
outputB = { ref = "$tasks.B.data" }

[[tasks]]
name = "A"
proof-perference = { type = "TEE", codeHash="d5a8bba00589dbd01abf7b8b92325fa8a3705c95642ec5b2a20bfed2b88a739d" }
[[tasks.input]]
arg0 = { ref = "$tasks.D.data" }
arg1 = { ref = "$tasks.C.data" }

[[tasks]]
name = "B"
proof-perference = "TEE"
[[tasks.input]]
arg = { ref = "$tasks.C.data" }

[[tasks]]
name = "C"
proof-perference = { type = "ecdsa", address = "0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5"}
[[tasks.input]]
arg = { ref = "$input.y" }

[[tasks]]
name = "D"
proof-perference = { type = "ecdsa", publicKey = "0x040acac15a20278bd5df8b2332287226d1320d9adffc6b6ad6c8ab24bba6a0428429526cec9efd90dffb3cff64baf49db1c5068d7b6cd00510a82a3a33a74e02d2"}
[[tasks.input]]
arg = { ref = "$input.y" }

```

The task's execution DAG is depicted in the chart below.&#x20;

<figure><img src="/files/UA8ZwkDaNg0ncuVISH5K" alt=""><figcaption><p>Example Query DAG</p></figcaption></figure>

Tasks \[`C`, `D`, `A`, `B`, `query`] will be dispatched and executed in order.  When receive `D`'s response, its proof will be validated in time. The validation processes are done as the same when `A`, `B` and `D` are completed. Note that query is a phantom task and it doesn't have proof.

The kernel will finally generate its attestation when all sub-task are validated.&#x20;

{% hint style="info" %}
The code hash of this attestation is equal to clique kernel. Retrive it from [here](https://example.com).
{% endhint %}

### On-Chain Verification

Users can create on-chain queries and await the execution results by using the [Smart Contract SDK](/build-with-clique/smart-contract-sdk). In the Smart Contract SDK, on-chain queries are actually created by the `CliqueTaskManager` contract. After the Clique Network executes the on-chain query, it submits the execution results and proofs to the `CliqueTaskManager`contract, which then verifies them. Upon successful verification, the results are returned to the user.

Next, we will detail how `CliqueTaskManager` verifies the execution results submitted by the Clique Network.

When the Clique Network submits execution results to `CliqueTaskManager`, it needs to provide the following information:

* query ID: The ID derived from the query parameters can be considered as a hash value of the query, which corresponds one-to-one with the query and is verifiable.
* response: The execution result of the query.
* proof: The proof used to verify this submission result.
* signature:  ECDSA signature over the query ID and the response.

When the Clique Network node first submits execution results to `CliqueTaskManager`, It will carry a TEE attestation in the proof. This TEE attestation is generated for a public key. `CliqueTaskManager` will verify this TEE attestation. If the verification is successful, it will extract the public key from it. Additionally, `CliqueTaskManager` will recover the public key from `(query ID, response, signature)` and compare it with the public key extracted from the attestation. If they match, the verification is successful, and the public key will be saved as a trusted public key.

`CliqueTaskManager` maintains a set of trusted public keys. After the public key is registered, subsequent submission of execution results can be verified through the trusted public key and the signature. That is to say, the Clique Network node only needs to carry the attestation during the first submission, and subsequent submissions do not require it. This is to reduce gas costs, as verifying the attestation on-chain is very expensive.

{% hint style="info" %}
The registered key is a ephemeral key. The ephemeral key must be regenerated each time the Clique Network node restarts. This is done to avoid potential security risks associated with storing keys. That is to say, after a restart, it needs to be registered again.
{% endhint %}

#### Verification steps

1. Recover the public key from `(query ID, response, signature)`
2. If this public key is one of the trusted public keys, use the signature to verify the `(query ID, response)`
3. If not, verify the attestation and compare the extracted public key. If the verification is successful and the public key matches, use the signature to verify the `(query ID, response)`


# Data Attestation

Clique provides various on-chain historical data sources. Check the following list to find what you need. For more information, please refer to a complete toolchain SDK here at [Clique Attestation SDK](/toolchain/clique-attestation-sdk).

#### List of Data Sources

* \[arbitrum one]
* \[ethereum mainnet]

### Example

A  more complex example pasted here:

```toml
name = "clique_arbitrumInfo"
spec-version = "1"
type = "Schema"

proof-type = ["TEE"]

[input]
address = { type = "string" }

[output]
createdBlock = { type = "u256", ref = "$tasks.clique_arbitrumCreatedBlock.data" }
lastActiveBlock = { type = "u256", ref = "$tasks.clique_arbitrumLastActiveBlock.data"}

[[tasks]]
name = "clique_arbitrumCreatedBlock"
proof-preference = "TEE"
[[tasks.input]]
address = { ref = "$input.address" }

[[tasks]]
name = "clique_arbitrumLastActiveBlock"
proof-preference = "TEE"
[[tasks.input]]
address = { ref = "$input.address" }
```

In this example,  we create a schema (phantom task) which includes two tasks -- [`clique_arbitrumCreatedBlock`](https://example.com), [`clique_arbitrumLastActiveBlock`](https://example.com), and reconstruct their outputs into the struct that we want.


# Social Verification

Clique supports different forms of social verification with end-to-end encrypted OAuth tokens.

#### List of Data Sources

* [Twitter](/sample-task-tutorials/social-verification/twitter)
* [Github](/sample-task-tutorials/social-verification/github)

### Example

The example illustrates how to pick up properties you needed. It's useful when you want to submit this to some contracts which may require a specific structure.

```toml
name = "example_twitterUserInfo"
spec-version = "1"
type = "Schema"

proof-type = ["TEE"]

[input]
username = { type = "string" }

[output]
createdDate = { type = "u64", ref = "$tasks.clique_twitterPublicInfo.createdAt" }
followerCount = { type = "u64", ref = "$tasks.clique_twitterPublicInfo.followerCount"}
updatedAt = { type = "u64", ref = "$tasks.clique_twitterPublicInfo.timestamp" }

[[tasks]]
name = "clique_twitterPublicInfo"
proof-preference = "TEE"
[[tasks.input]]
username = { ref = "$input.address" }
```


# Github


# Twitter


# Making Arbitrary TLS Calls (TLS Oracle)

Clique supports clients to make arbitrary TLS calls from smart contracts in a verifiable format. For generic TLS calls, we have provided the generic `clique_httpsRequest` Built-In task. Users can create queries for the `clique_httpsRequest` task to obtain the results of TLS calls. Users can also create more complex tasks of `Schema` type to utilize the `clique_httpsRequest` task.

### clique\_httpsRequest

Here is the manifest file for the `clique_httpsRequest` task:

```toml
spec-version = "1"
name = "clique_httpsRequest"
type = "BuiltIn"

proof-type = ["TEE"]

[types.Transformation]
from = { type = "string", description = "json pointer to field in response" }
soltype = { type = "string", description = "solidity type" }

[input]
url = { type = "string", description = "Request url" }
encoding = { type = "Transformation[]", description = "encoding format" }

[output]
response = { type = "bytes", description = "ABI encoded" }
```

`clique_httpsRequest` is a built-in task, which means users can directly use this task within the Clique Network without the need to publish it additionally.

This task has two output parameters:

* `url`: The URL to be accessed for this TLS call. The URL needs to return parseable results in JSON format.
* `encoding`: Indicates how to extract data from the returned JSON result. Here we use an array of custom types (`Transformation`) as the input parameter. The `Transformation` custom type contains two fields: `from` is a JSON pointer for extracting data from JSON, and `soltype` is the Solidity type into which the extracted data should be encoded.

This task has only one return value: `response`. The `response` is data encoded in Solidity ABI format, with the encoding format specified by the input parameter `encoding`. After obtaining the result of the TLS call, the smart contract can decode the data using ABI decoding to retrieve the information.

### Make TLS Calls from Smart Contracts

Here is a smart contract example, initiating a TLS call to <https://jsonplaceholder.typicode.com/users> and extracting data.

This URL will return JSON data in the following format:

```json
[
    {
        "id": 1,
        "name": "Leanne Graham",
        "username": "Bret",
        "email": "Sincere@april.biz",
        "address": {
            "street": "Kulas Light",
            "suite": "Apt. 556",
            "city": "Gwenborough",
            "zipcode": "92998-3874",
            "geo": {
                "lat": "-37.3159",
                "lng": "81.1496"
            }
        },
        "phone": "1-770-736-8031 x56442",
        "website": "hildegard.org",
        "company": {
            "name": "Romaguera-Crona",
            "catchPhrase": "Multi-layered client-server neural-net",
            "bs": "harness real-time e-markets"
        }
    },
    ...
]
```

In the following example, we will use TLS Call to extract `id`, `name`, `lat`, and the entire JSON array from the returned JSON result.

```solidity
pragma solidity ^0.8.22;

import {ICliqueTaskManager} from "../src/ICliqueTaskManager.sol";

struct Transformation {
    string from;
    string soltype;
}

struct Params {
    string url;
    Transformation[] encoding;
}

struct Response {
    bytes response;
}

struct Result {
    uint32 id;
    string name;
    string geoLat;
    string[] array;
}

contract HttpsRequest {
    address public immutable _manager;

    event CallbackInvoked(Result);

    constructor(address manager) {
        _manager = manager;
    }

    function callback(bytes calldata _response) external {
        Response memory response = abi.decode(_response, (Response));
        Result memory result = abi.decode(response.response, (Result));
        emit CallbackInvoked(result);
    }

    function run(uint32 id) public {
        Transformation[] memory transformations = new Transformation[](4);
        transformations[0] = Transformation({from: "/0/id", soltype: "uint32"});
        transformations[1] = Transformation({from: "/0/name", soltype: "string"});
        transformations[2] = Transformation({from: "/0/address/geo/lat", soltype: "string"});
        transformations[3] = Transformation({from: "", soltype: "string[]"});

        Params memory params = Params({
            url: "https://jsonplaceholder.typicode.com/users",
            encoding: transformations
        });

        ICliqueTaskManager.Task memory task = ICliqueTaskManager.Task(
            id,
            "clique_httpsRequest",
            abi.encode(params)
        );
        ICliqueTaskManager(_manager).createNewTask{value: 0.05 ether}(
            abi.encode(task),
            this.callback.selector
        );
    }
}
```

Let's break down the example.

```solidity
import {ICliqueTaskManager} from "../src/ICliqueTaskManager.sol";
```

Import the Clique Contract SDK here.

```solidity
struct Transformation {
    string from;
    string soltype;
}
```

Define the custom type`Transformation` for the `clique_httpsRequest` task. The name of the structure is not important, but the content of the structure must be consistent with the custom type in`clique_httpsRequest` task.&#x20;

The names of the other structures to be defined next are not important; users can define names as they wish.

```solidity
struct Params {
    string url;
    Transformation[] encoding;
}
```

Define the input parameters according to the input type of the `clique_httpsRequest` task.

```solidity
struct Response {
    bytes response;
}
```

Define the output parameters according to the output type of the `clique_httpsRequest` task.

```solidity
struct Result {
    uint32 id;
    string name;
    string geoLat;
    string[] array;
}
```

Define the decoded result of the TLS call. The `clique_httpsRequest` task will return the encoded result, which will be decoded according to this structure.

```solidity
Transformation[] memory transformations = new Transformation[](4);
transformations[0] = Transformation({from: "/0/id", soltype: "uint32"});
transformations[1] = Transformation({from: "/0/name", soltype: "string"});
transformations[2] = Transformation({from: "/0/address/geo/lat", soltype: "string"});
transformations[3] = Transformation({from: "", soltype: "string[]"});
```

Create the `Transformation` structure needed in the input parameters, using JSON Pointer to specify how to extract data from the JSON result, and determine how to encode the extracted data. The result data will be encoded in the order specified by the `Transformation` array.

```solidity
Params memory params = Params({
    url: "https://jsonplaceholder.typicode.com/users",
    encoding: transformations
});
```

Construct the input parameters.

```solidity
ICliqueTaskManager.Task memory task = ICliqueTaskManager.Task(
    id,
    "clique_httpsRequest",
    abi.encode(params)
);
```

Construct the `clique_httpsRequest` query.&#x20;

{% hint style="info" %}
Each time a query is created, a **different** ID needs to be specified. If the content of the query is exactly the same, Clique Network will not create a new query.
{% endhint %}

```solidity
ICliqueTaskManager(_manager).createNewTask{value: 0.05 ether}(
    abi.encode(task),
    this.callback.selector
);
```

Use the Clique Contract SDK to create a query and wait for the callback function to execute.

```solidity
function callback(bytes calldata _response) external {
    Response memory response = abi.decode(_response, (Response));
    Result memory result = abi.decode(response.response, (Result));
    emit CallbackInvoked(result);
}
```

Define the callback function and decode the result of the TLS call within the callback function.

### Make TLS Calls from Client SDK

Although the primary use case for TLS Calls is in smart contracts, it is also supported off-chain. Users can use the [Clique Client SDK](/build-with-clique/clique-client-sdk) to call the `clique_httpsRequest` task.

For example, use our Rust SDK:

Add this dependency to your `Cargo.toml`

```toml
clique-client-sdk = { git = "https://github.com/CliqueOfficial/clique-protocol-sdk" }
serde_json = { version = "1.0", features = ["preserve_order"] }
tokio = { version = "1.38.0", features = ["full"] }
```

```rust
use clique_client_sdk::CliqueClient;
use serde_json::json;

#[tokio::main]
async fn main() {
    let endpoint = "https://localhost:8000";
    let client = CliqueClient::new(endpoint).unwrap();

    let id = 1;
    let url = "https://jsonplaceholder.typicode.com/users";
    let encoding = json!([
        {"from": "/0/id", "soltype": "int16"},
        {"from": "/0/name", "soltype": "string"},
        {"from": "/0/address/geo/lat", "soltype": "string"}
    ]);
    let json_query = json!({
        "id": id,
        "method": "clique_httpsRequest",
        "params": {"url": url, "encoding": encoding },
        "input_types": {"url": "string", "encoding": "Transformation[]"},
        "custom_types": {"Transformation": {"from": "string", "soltype": "string"}}
    });
    let result = client.run_query(json_query).await.unwrap();
}
```

### Make TLS Calls through Schema Task

In addition to directly using the `clique_httpsRequest` task, users can also customize their own `Schema` tasks and indirectly use `clique_httpsRequest` within these `Schema` tasks to construct more complex queries.

Here is a simple example of a `Schema` task's manifest file. After defining the manifest file, users need to first publish it to the Clique Network using [Clique CLI](/build-with-clique/clique-cli), and then create the corresponding query to use it.

```toml
specVersion = "1"
name = "yourOrganization_customRequest"
type = "Schema"

proof-type = ["TEE"]

[types.Transformation]
from = { type = "string", description = "json pointer to field in response" }
soltype = { type = "string", description = "solidity type" }

[input]
url = { type = "string", description = "Request url" }
encoding = { type = "Transformation[]", description = "encoding format" }

[output]
response = { ref = "$tasks.clique_httpsRequest.response" }

[[tasks]]
name = "clique_httpsRequest"
proof-preference = "TEE"
[tasks.input]
url = "$input.url"
encoding = "$input.encoding"
```


# Custom Executor

Clique offers a wide range of tasks officially for various use cases. If these do not meet your requirements, you can create your own executors to cater to specific tasks seamlessly.

### Development Tools

To assist developers in quickly implementing a custom executor, Clique provides Rust [procedural macro](https://doc.rust-lang.org/reference/procedural-macros.html) support. Rust developers can directly use the procedural macros we provide to encapsulate the custom executor. Developers do not need to be concerned with how the executor interacts with the Clique network; they only need to focus on their own computational logic.

First, include the following dependencies in your Rust project:

```toml
clique-proc-macro = { git = "https://github.com/CliqueOfficial/clique-protocol-sdk" }
clique = { git = "https://github.com/CliqueOfficial/clique-protocol-sdk" }
```

Clique provides the following procedural macros:

* `#[namespace(name = ...)]`
  * The `namespace` macro ensures that all tasks within the annotated module are grouped under a specific namespace, and the namespace is corresbonding to the `name` in the Clique Task Manifest. For example, if the task's name is "clique\_httpsRequest," then the namespace should be specified as "clique."
* `#[task]`
  * The `task` macro is used to define a task struct. This macro annotates a struct that represents a task, allowing it to be recognized and managed by the task execution system.
  * You need to implement the `clique::Task` trait for the struct marked with the `task` macro, and within the `execute` method, implement your actual computational logic. Note that the input and output of the `execute` method are Rust struct generated based on the `input` and `output` section of your Clique Task Manifest file. You can directly use the field name from the manifest to access the corresbonding field in the input / output.
* `#[clique::async_trait]`
  * This macro is used to annotate the implementation of `clique::Task` trait, since this trait is `async`
* `#[executor(with(...))]`
  * The `executor` macro is used to define an executor struct that can handle the execution of multiple task modules. In the `with` field, fill in the name of the module decorated with the `namespace` macro. The tasks within these modules will be imported into your custom executor.

Here is an example:

```rust
use clique_proc_macro::{executor, namespace};

#[namespace(name = "yourOrganization")]
pub mod task_mod1 {
    #[task]
    pub struct HttpsRequest;

    #[clique::async_trait]
    impl clique::Task for HttpsRequest {
        type Error = anyhow::Error;

        async fn execute(
            input: Self::Input,
        ) -> Result<Self::Output, Self::Error> {
            let url = input.url;
            let encoding = input.encoding;

            for transformation in encoding.into_iter() {
                let json_ptr_str: String = transformation.from;
                let soltype_str: String = transformation.soltype;
                // ...
            }

            let response: Vec<u8> = // ...
            let output = HttpsRequestOutput { response };
            Ok(output)
        }
    }
    
    #[task]
    pub struct HttpsRequest2;

    #[clique::async_trait]
    impl clique::Task for HttpsRequest2 {
        type Error = anyhow::Error;

        async fn execute(
            input: Self::Input,
        ) -> Result<Self::Output, Self::Error> {
            // ...
        }
    }
}

#[namespace(name = "yourOrganization")]
pub mod task_mod2 {
    #[task]
    pub struct AnotherTask;

    #[clique::async_trait]
    impl clique::Task for AnotherTask {
        type Error = anyhow::Error;

        async fn execute(
            input: Self::Input,
        ) -> Result<Self::Output, Self::Error> {
            // ...
        }
    }
}

#[executor(with(
    task_mod1,
    task_mod2,
))]
pub struct MyCustomExecutor;
```


# Clique Distributions

Configure batch token distributions with strategies, hooks, windows, fees, and signer-controlled release.

Clique Distributions lets you run configurable token drops across batches (Merkle roots), with signer-controlled partial releases, per-batch fees, native/erc-20 delivery, and composable **hooks** (modules) such as direct transfer, time-based penalties, or linear vesting streams.

***

### What you can do

* Upload & track allocations for investors, team, advisors, and community
* Choose **Airdrop (direct transfer)** or **Claim (escrow pull)** per batch
* Mix strategies per batch via **hooks** and a **fallback** remainder
* Enforce **windows**, **fees**, and **release gates**
* White-label claim portal; granular roles & audit log

{% hint style="info" %}
Quickstart Jump straight to **Quickstart → Step 1** to get your first distribution live.&#x20;
{% endhint %}

**Admins**: see **How to Fund Allocations**\
**Engineers**: start at **Developer → Overview**

***

### Key concepts

* **Batch / Root**: Merkle root committing to `(handler, totalAllocation, ...)`.
* **Handler**: Opaque identity; with fixed recipients, `handler == keccak256(recipient)`.
* **Released**: Signer-attested cumulative cap; claim enforces `amount ≤ released - previouslyClaimed`.
* **Strategy**: Ordered hooks by proportion plus a fallback hook.
* **Hook**: Modular executor that consumes an allocated portion (`consumed`) via `hookTransfer`.
* **Fees**: First-claim-only per `(root, handler)`: `None | Fixed | SingleTier{rate,min,max}`.

**Next:** [Quickstart](/token-distribution/quickstart)


# Quickstart


# Setup

Add tokens, admin wallets, and set up distributor strategies/hooks.

This step preps your project for distributions.

### 1A. Project details

* Name, chain(s), logo, contact email/support links.
* (Optional) White-label claim portal settings.

### 1B. Add project token(s)

* Enter token `symbol`, `decimals`, `chain`, `address`.
* Not minted yet? Flag as **pre-mint** and proceed; allocations can be staged.

### 1C. Admin wallet(s)

* Support: EOA, Gnosis Safe (multisig).
* On-chain distributions require funding from this wallet or escrow.

### 1D. Distributor configuration(s)

Define a **configuration** with `strategies[]` (proportion, hook) and a **fallback hook**:

* Immediate ERC‑20 airdrop → 100% `TransferHook`
* Native airdrop (unwrap) → `isWrappedToken=true` + `TransferHook`
* Time penalty → `LinearPenaltyHook` (non-fallback), fallback `TransferHook`
* Full vesting → `CliqueLockHook`
* 70/30 split → 70% `TransferHook`, fallback `CliqueLockHook` (30%)

### 1E. Team & roles

* Roles: **Super Admin**, **Admin**, **Viewer**.
* Enable 2FA; all actions appear in **Audit Log**.

**Next:** **Step 2 — Schedules & Releases**\
**Back to:** [Quickstart](/token-distribution/quickstart)


# Schedules and Releases

Model unlock/vesting and configure signer-attested release limits.

### Unlock vs Vesting

* **Unlock schedule**: time-based milestones that make tokens eligible to claim.
* **Vesting**: deliver eligible tokens via a **CliqueLock** linear stream.

You can use unlock-only, vesting-only, or unlock that feeds vesting.

### Signer-controlled `released`

An off-chain service tracks per-handler `released` (cumulative).\
A signer (EIP‑712) attests `{ root, handler, released, onBehalfOf?, deadline }`.\
The contract enforces: `amount ≤ released - previouslyClaimed`.

#### Dynamic vs fixed recipient

* **Fixed**: Merkle leaf binds recipient: `handler == keccak256(onBehalfOf)`.
* **Dynamic**: Signer includes `onBehalfOf` in signature; Merkle doesn’t hard-bind.

### Map roots to configurations

For each Merkle `root`, set `configurationId[root]` to the configuration you created in Step 1.\
Roots may reuse or override fees and windows.

**Next:** **Step 3 —** [Onboarding CSV](/token-distribution/quickstart/onboarding-csv)

**Prev:** **Step 1 —** [Setup](/token-distribution/quickstart/setup)


# Onboarding CSV

Import allocations, validate, and generate a Merkle root.

### Template columns

`handler`, `recipientEmail?`, `wallet?`, `tokenSymbol`, `totalAllocation`, `scheduleRef`, `category`, `notes`

* `handler`: If fixed-recipient mode, use `keccak256(recipient)`. Else, any stable identifier.
* `scheduleRef`: References an unlock/vesting template from Step 2.

### Upload & validation

* Duplicate detection, per-cohort totals, email/wallet format checks.
* Dry-run generates a **Merkle root** and a diff report.

**Next:** **Step 4 —** [Dry Run and Go Live](/token-distribution/quickstart/dry-run-and-go-live)\
**Prev:** **Step 2 —** [Schedules and Releases](/token-distribution/quickstart/schedules-and-releases)


# Dry Run and Go Live

### Test transactions

* Use testnet to simulate **Airdrop** and **Claim** paths.
* Verify window/fee enforcement and hook accounting.

### Funding checks & top-ups

* For **Claim (escrow)** flows, deposit enough to cover through a target date; dashboard shows “Funded Until” and recommends top-up amounts.

### Launch checklist

* Signer domain/version pinned
* Roots ↔ configurations verified
* Window open; fee mode correct; flags (`dynamicRecipient`, `isWrappedToken`) correct
* Hooks wired; balances sufficient
* Claim portal enabled; recipient comms ready

**Prev:** **Step 3 —** [Onboarding CSV](/token-distribution/quickstart/onboarding-csv)


# What is Clique Wallet?

Clique Wallet is an embedded, custodial wallet infrastructure that empowers users and applications to securely manage digital assets and transact on multiple blockchains, including Solana, EVM-compatible chains, Hyperliquid, and more.

Unlike traditional wallet solutions, Clique Wallet eliminates the trade-off between security and convenience. Through innovative use of **Trusted Execution Environment (TEE)** technology—specifically Intel SGX—Clique Wallet ensures that private keys remain completely inaccessible to anyone, including service operators, while providing a seamless user experience that requires no seed phrase management or complex setup.

Clique Wallet provides a comprehensive wallet solution that can be embedded directly within your application, enabling users to interact with blockchain networks without requiring separate wallet clients like browser extensions or mobile apps. Whether you're building a consumer-facing DeFi application, an enterprise treasury management system, a trading platform, or any other blockchain-enabled product, Clique Wallet provides the secure, user-friendly wallet infrastructure you need to deliver exceptional user experiences.

#### Why Clique Wallet?

Traditional wallet solutions force users to choose between security and convenience. Self-custodial wallets require users to manage complex seed phrases and private keys, creating barriers to adoption. Traditional custodial wallets, while convenient, require users to trust service operators with their private keys—a significant security risk.

Clique Wallet solves this fundamental problem by combining the best of both worlds: the convenience of a custodial wallet with the security guarantees of a self-custodial solution. By leveraging hardware-level security through TEE technology, Clique Wallet ensures that even service operators cannot access user private keys, while maintaining the frictionless experience users expect from modern applications.

#### Key Highlights

**🔒 Hardware-Level Security**: Clique Wallet leverages TEE (specifically Intel SGX) technology to create hardware-protected enclaves where all cryptographic operations occur. This means private keys are never exposed in plaintext, even to privileged system processes or service operators.

**🚀 Zero-Friction Onboarding**: Users can create and access wallets instantly through familiar authentication methods—social media accounts (Google, Apple, X/Twitter, Telegram), email, phone (SMS), or by connecting existing external wallets (MetaMask, Phantom, Okx, Rabby, Coinbase Wallet). No seed phrases, no complex setup.

**🌐 Multi-Chain Native**: Built from the ground up to support Solana, EVM-compatible chains, Hyperliquid, and more. Users can manage assets across different blockchain ecosystems from a single unified account.

**💼 Multiple Wallets**: Create one primary wallet and multiple sub-wallets on each supported blockchain. Perfect for separating personal and business assets, managing different trading strategies, or organizing funds by purpose.

**🔧 Programmatic Access**: Comprehensive REST API with customizable permission scopes and IP whitelisting. Enable automated trading, treasury management, cross-chain operations, and other programmatic use cases with fine-grained access control.

**🛡️ Enterprise-Grade Security**: Multi-layered security architecture including TEE protection, encrypted storage, data integrity verification, secure communication, and session security. All designed to protect user assets and data at every layer.

**📱 Embedded Experience**: Seamlessly integrate wallet functionality directly into your application. Users sign transactions within your interface—no redirects, no external wallet popups, no friction.

**🔄 Export Capability**: Users maintain full control with the ability to export their private keys at any time, providing an escape hatch and ensuring true ownership of their assets.


# Key Concepts

Understanding Clique Wallet requires familiarity with several key concepts:

**Embedded Wallets**: Unlike traditional wallet applications that require separate installations or browser extensions, Clique Wallet's embedded wallets are integrated directly into your application. Users interact with their wallets seamlessly within your interface, creating a unified experience without context switching.

**Trusted Execution Environment (TEE)**: TEE is a secure area within a processor that ensures code and data are protected from unauthorized access, even from privileged software. Clique Wallet uses Intel SGX, a specific TEE implementation, to create hardware-protected enclaves where all cryptographic operations—key generation, storage, and transaction signing—are performed in complete isolation.

**Custodial vs. Self-Custodial**: Traditional custodial wallets give service operators access to user private keys, creating a trust dependency. Self-custodial wallets give users full control but require them to manage seed phrases and private keys. Clique Wallet combines both approaches: users get the convenience of a custodial wallet (no seed phrase management) with the security guarantees of self-custody (service operators cannot access keys).

**Multi-Chain Support**: Clique Wallet natively supports multiple blockchain networks, allowing users to manage assets across different ecosystems from a single account. Each network type (Solana, EVM-compatible chains, Hyperliquid) has its own wallet addresses, but they're all managed under one unified user account.

**Wallet Sets**: Users can create multiple wallets on each supported blockchain. The primary wallet (Main) is created automatically, while additional wallets (Forward wallets, Secondary wallets) can be created for different purposes such as separating funds, managing different trading strategies, or organizing assets by use case.

**Authentication Methods and Account Binding**: Clique Wallet supports multiple authentication methods including social OAuth (Google, X/Twitter, Telegram, etc.), email/phone verification, Apple Sign-In, and external wallet connections (MetaMask, Phantom, Okx, Rabby, Coinbase Wallet, etc.). Users can bind multiple authentication methods to a single account, enabling flexible access while maintaining the same wallets and assets.

**API Keys**: For programmatic access, Clique Wallet provides API keys with customizable permission scopes. These keys enable automated operations while maintaining security through IP whitelisting and granular permission controls.

**Export Functionality**: Users can export their private keys through a secure two-step process with verification. This provides an escape hatch, allowing users to migrate their wallets to other services if needed. The export process requires active authentication with verification to prevent unauthorized access.


# Supported Chains

Clique Wallet provides native support for multiple blockchain networks:

* **Solana**: Full support for the Solana blockchain. Users can create Solana wallets, sign Solana transactions, and interact with Solana-based applications and protocols.
* **EVM-Compatible Chains**: Support for Ethereum Virtual Machine (EVM) compatible blockchains, including Ethereum, Base, Arbitrum, BNB Smart Chain, HyperEVM, and more. All EVM-compatible chains share the same wallet address format, allowing users to use the same address across multiple EVM networks. This enables seamless interaction with DeFi protocols, NFT marketplaces, and other applications built on EVM-compatible networks.
* **Hyperliquid**: Native support for Hyperliquid's two chains: HyperEVM and HyperCore. HyperEVM is an EVM-compatible chain, while HyperCore is a non-EVM L1 chain used for executing L1 actions (such as opening orders and changing leverage). Both chains use the same EVM wallet address, enabling users to interact with Hyperliquid's trading infrastructure and DeFi protocols across both networks.

Clique Wallet's extensible architecture supports adding new blockchain networks as they gain adoption, ensuring users can access emerging ecosystems and protocols.


# How It Works

Clique Wallet is designed with security and user experience at its core. Our architecture is built on the principle that users should never have to compromise between security and convenience. By implementing TEE technology, we've created a wallet infrastructure where cryptographic operations are protected at the hardware level, ensuring that sensitive data remains secure even in the event of software vulnerabilities or insider threats. This approach delivers enterprise-grade security without sacrificing the seamless user experience that drives adoption.

As an embedded wallet service, Clique Wallet integrates directly into your application. Users authenticate through various methods—social login, email/phone verification, or external wallet connections. Upon first login, Clique Wallet automatically generates secure wallets for all supported blockchains within the TEE. All private keys are generated, stored, and managed entirely within the TEE's encrypted enclaves, ensuring they never leave the secure environment. When users sign transactions, the signing operation is performed within the TEE, maintaining complete key isolation. Secure HTTP-only session cookies maintain user authentication state throughout their session.

This architecture makes Clique Wallet ideal for:

* **Trading Platforms**: Integrate wallet functionality for users to deposit, trade, and withdraw assets across multiple chains
* **Consumer Applications**: Enable users to interact with DeFi protocols, NFT marketplaces, and other blockchain applications without managing seed phrases
* **Enterprise Solutions**: Provide secure wallet infrastructure for businesses managing treasury operations or customer assets
* **Gaming & Metaverse**: Offer seamless wallet experiences for in-game purchases and virtual asset management
* **Developer Tools**: Provide programmatic wallet access for automated trading bots, cross-chain bridges, and other infrastructure services


# Getting Started

Choose the guide that best fits your needs:

* [**For Users**](/clique-wallet/getting-started/for-users): Learn how to use Clique Wallet as an end user
* [**SDK Integration**](/clique-wallet/getting-started/sdk-integration): Integrate Clique Wallet using SDK
* [**REST API Integration**](/clique-wallet/getting-started/rest-api-integration): Integrate Clique Wallet using REST API


# For Users

This guide is for end users who want to start using Clique Wallet in an application that has already integrated it.

#### Creating Your First Wallet

1. **Access the Application**: Navigate to the application that uses Clique Wallet
2. **Choose Your Login Method**: You can log in using:
   * Social accounts (Google, X/Twitter, Telegram, Apple, etc.)
   * Email address
   * Phone number
   * External wallet (MetaMask, Phantom, Okx, Rabby, Coinbase Wallet, etc.)

#### Logging In with Email/Phone Number

1. Enter your email address or phone number
2. Check your email or phone for a verification code
3. Enter the verification code to complete login
4. Your wallets are automatically created for all supported blockchains

#### Logging In with Social Account

1. Click on your preferred social login option (Google, X/Twitter, Telegram, Apple, etc.)
2. Authorize the application to access your social account
3. You'll be redirected back and automatically logged in
4. Your wallets are automatically created

#### Logging In with External Wallet

1. Click "Connect Wallet" and select your wallet (MetaMask, Phantom, Okx, Rabby, Coinbase Wallet, etc.)
2. Sign the challenge message with your external wallet
3. You'll be logged in and your Clique Wallet will be created

#### After Login

Once logged in, you can:

* **View Your Wallet Addresses**: Your wallet addresses for Solana, EVM-compatible chains, and Hyperliquid are automatically created
* **Sign Transactions**: Sign transactions directly within the application interface
* **Manage Multiple Wallets**: Create additional wallets for different purposes
* **Bind Multiple Login Methods**: Add additional authentication methods to your account for redundancy

#### Security Tips

* **Bind Multiple Authentication Methods**: Add email, social login, or external wallet connections to your account. This ensures you can always access your account even if you lose access to one method
* **Export Your Keys**: You can export your private keys at any time through the export functionality if you want to migrate your wallets to another service
* **Keep Your Session Active**: Your session will remain active as you use the application, but will expire after inactivity for security


# SDK Integration

This guide helps developers integrate Clique Wallet into their applications using the official SDK. The Clique Wallet SDK is available as an npm package and provides a convenient way to interact with Clique Wallet's API.

#### Prerequisites

* Access to a Clique Wallet instance
* The Clique Wallet API endpoint URL
* Node.js 16+ or a modern JavaScript environment

#### Installation

Install the Clique Wallet SDK using npm:

```bash
npm install clique-wallet-sdk
```

Or using yarn:

```bash
yarn add clique-wallet-sdk
```

For more information, visit the [Clique Wallet SDK on npm](https://www.npmjs.com/package/clique-wallet-sdk).

#### Basic Usage

**Initialize the SDK**

```javascript
import { CliqueWallet } from 'clique-wallet-sdk';

const wallet = new CliqueWallet({
  apiUrl: 'https://your-wallet-instance.com'
});
```

**Authenticate User**

```javascript
// Request verification code
await wallet.sendVerification({ email: 'user@example.com' });

// Complete login with verification code
const user = await wallet.login({
  type: 'Email',
  data: {
    email: 'user@example.com',
    code: '123456'
  }
});
```

**Get Wallet Addresses**

```javascript
// Get current session and wallet information
const session = await wallet.getSession();

// Access wallet addresses
const ethereumWallet = session.wallets.find(w => w.network === 'Ethereum');
const solanaWallet = session.wallets.find(w => w.network === 'Solana');
```

**Sign Transaction**

```javascript
const signature = await wallet.sign({
  address: '0x...',
  network: 'Ethereum',
  message: '0x...',
  need_check: true
});
```

#### Authentication Methods

The SDK supports all authentication methods available in Clique Wallet:

**Email/Phone Verification:**

```javascript
await wallet.sendVerification({ email: 'user@example.com' });
// or
await wallet.sendVerification({ phone: '+1234567890' });
```

**Social OAuth:**

```javascript
// Initialize OAuth flow
const oauthUrl = await wallet.oauth.init({
  provider: 'google',
  redirectUri: 'https://yourapp.com/callback'
});

// After OAuth callback, complete login
await wallet.login({
  type: 'GoogleOAuth',
  data: { state, code, code_verifier }
});
```

**External Wallet Connection:**

```javascript
// Get challenge
const challenge = await wallet.getChallenge({
  method: 'metamask',
  id: '0x...'
});

// After user signs, complete login
await wallet.login({
  type: 'MetaMask',
  data: { wallet_address, challenge, signature }
});
```

#### Error Handling

The SDK provides structured error handling:

```javascript
try {
  const user = await wallet.login({ /* ... */ });
} catch (error) {
  if (error.status === 401) {
    // Handle authentication error
  } else if (error.status === 400) {
    // Handle bad request
  } else {
    // Handle other errors
  }
}
```


# REST API Integration

Authenticate a user and fetch their wallets.

This guide helps developers integrate Clique Wallet into their applications using the RESTful API.

#### Prerequisites

* Access to a Clique Wallet instance
* The Clique Wallet API endpoint URL
* A web application or backend service where you want to integrate Clique Wallet
* Basic understanding of REST APIs and HTTP requests

#### Basic Setup

**1. Configure Your Clique Wallet Endpoint**

First, configure your application to point to your Clique Wallet instance:

```javascript
const WALLET_API_URL = 'https://your-wallet-instance.com';
```

**2. Understand the Authentication Flow**

Clique Wallet uses session-based authentication for user-facing applications. When a user successfully authenticates, Clique Wallet sets a secure HTTP-only session cookie that maintains the user's authentication state.

#### Your First Integration

**Step 1: User Authentication**

Users can authenticate using various methods. Here's a simple example using email verification:

**Request a Verification Code:**

```bash
curl -X POST https://your-wallet-instance.com/send_verification \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com"
  }'
```

**Complete Login:**

After the user receives and enters the verification code:

```bash
curl -X POST https://your-wallet-instance.com/login \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "type": "Email",
    "data": {
      "email": "user@example.com",
      "code": "123456"
    }
  }'
```

Upon successful login, Clique Wallet will:

* Create wallets for all supported blockchains (if they don't exist)
* Set a secure session cookie
* Return user information including wallet addresses

**Step 2: Check Session Status**

To verify the user is authenticated and get their wallet information:

```bash
curl -X GET https://your-wallet-instance.com/session \
  -H "Content-Type: application/json" \
  -b cookies.txt
```

The response will include:

* User ID
* Wallet addresses for all supported networks (Solana, EVM-compatible chains, etc.)
* Authentication methods bound to the account

**Step 3: Get Wallet Addresses**

Wallet addresses are automatically created upon first login. You can retrieve them from the session response:

```json
{
  "id": "user-id",
  "wallets": [
    {
      "id": "wallet-id",
      "address": "0x...",
      "network": "Ethereum",
      "wallet_type": "Embedded",
      "wallet_set": "Main"
    },
    {
      "id": "wallet-id",
      "address": "So1...",
      "network": "Solana",
      "wallet_type": "Embedded",
      "wallet_set": "Main"
    }
  ]
}
```

**Step 4: Sign Your First Transaction**

To sign a transaction, send the transaction data to the sign endpoint:

```bash
curl -X POST https://your-wallet-instance.com/sign \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{
    "address": "0x...",
    "network": "Ethereum",
    "message": "0x...",
    "need_check": true
  }'
```

The response will include the signature that can be used to submit the transaction to the blockchain.

#### Authentication Methods

Clique Wallet supports multiple authentication methods:

**Social OAuth (Google, X/Twitter, Telegram):**

1. Initialize OAuth flow with `/oauth/init`
2. Redirect user to the OAuth provider
3. Handle callback at `/oauth/callback`
4. Complete login with `/login` using the OAuth credentials

**External Wallet Connection:**

1. Get challenge message from `/challenge`
2. User signs the challenge with their external wallet
3. Complete login with `/login` using the signature

**Phone Verification:** Similar to email verification, but use `phone` instead of `email` in the request.

#### Common Patterns

**Checking if User is Logged In:**

```javascript
async function checkAuthStatus() {
  const response = await fetch('https://your-wallet-instance.com/session', {
    credentials: 'include' // Important: include cookies
  });
  
  if (response.ok) {
    const user = await response.json();
    return user;
  }
  return null;
}
```

**Handling Session Expiration:**

```javascript
async function ensureAuthenticated() {
  const user = await checkAuthStatus();
  if (!user) {
    // Redirect to login
    window.location.href = '/login';
    return null;
  }
  return user;
}
```

**Error Handling:**

```javascript
try {
  const response = await fetch('https://your-wallet-instance.com/sign', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
    body: JSON.stringify(signRequest)
  });
  
  if (!response.ok) {
    const error = await response.json();
    console.error('Sign error:', error.error);
    // Handle error appropriately
  } else {
    const result = await response.json();
    // Use the signature
  }
} catch (error) {
  console.error('Network error:', error);
}
```


# Features & Capabilities

Clique Wallet provides a comprehensive set of features designed to meet the needs of both end users and developers. This section covers the core capabilities and advanced features available in Clique Wallet.


# Multiple Chains

Clique Wallet provides native support for multiple blockchain networks, allowing users to manage assets across different ecosystems from a single unified account.

#### Unified Account Management

All wallets across different blockchains are managed under a single user account:

* **Single Authentication**: One login provides access to all wallets across all networks
* **Unified Interface**: Manage all wallets through a single interface
* **Cross-Chain Operations**: Perform operations across different chains from the same account

#### Network-Specific Features

Each supported network has its own characteristics:

**Solana:**

* Native Solana wallet addresses
* Support for Solana's transaction format
* Integration with Solana-based applications and protocols

**EVM-Compatible Chains:**

* Shared wallet address format across all EVM chains
* Same address works on Ethereum, Base, Arbitrum, BNB Smart Chain, HyperEVM, and more
* Support for EIP-712 and standard Ethereum transaction formats

**Hyperliquid:**

* Support for both HyperEVM (EVM-compatible) and HyperCore (non-EVM L1)
* Same EVM wallet address used for both chains
* Integration with Hyperliquid's trading infrastructure

#### Extensibility

Clique Wallet's architecture supports adding new blockchain networks as they gain adoption. The extensible design ensures that users can access emerging ecosystems and protocols without requiring major infrastructure changes.


# Multiple Wallets

Clique Wallet allows users to create and manage multiple wallets on each supported blockchain, providing flexibility for organizing assets and managing different use cases.

#### Wallet Sets

Each wallet belongs to a **wallet set**, which determines its purpose and how it's derived from the master key. Clique Wallet uses **BIP32 (Bitcoin Improvement Proposal 32)** hierarchical deterministic (HD) wallet standard to derive all wallet keys from a single master key. This ensures that all wallets are cryptographically related and can be managed under a single account while maintaining separate addresses and balances.

* **Main Wallet**: The primary wallet created automatically for each network upon first login. This is the default wallet for most operations and serves as the primary wallet for each blockchain network.
* **Secondary Wallets**: Additional wallets for separating funds and managing multiple transaction flows. Secondary wallets are identified by an index (0, 1, 2, etc.) and provide another layer of organization for users who need to separate personal and business assets, manage different trading strategies, or organize funds by purpose.
* **Forward Wallets**: Additional wallets designed for specific purposes and use cases. Forward wallets are identified by an index and are ideal for applications that need dedicated wallets for particular functions or workflows.

#### Use Cases for Multiple Wallets

Multiple wallets enable various organizational strategies:

* **Fund Separation**: Use Secondary wallets to separate personal and business assets, or organize funds by purpose (savings, trading, DeFi operations)
* **Trading Strategies**: Use Secondary wallets for different trading strategies or risk profiles, managing multiple transaction flows simultaneously
* **Application-Specific Wallets**: Allocate Forward wallets for specific applications or protocols that require dedicated wallet addresses
* **Purpose-Specific Operations**: Use Forward wallets for specific purposes such as automated forwarding, escrow-like operations, or dedicated workflows

#### Creating Additional Wallets

Additional wallets can be created through the API. When creating a wallet, you specify:

* The network (Solana, Ethereum, etc.)
* The wallet set type (Forward or Secondary)
* The wallet index (for Forward or Secondary wallets)

All wallets within the same wallet set share the same user account and authentication, but have separate addresses and balances.


# Account Binding

Account binding allows users to link multiple authentication methods to a single Clique Wallet account, providing flexibility and redundancy in account access.

#### How Account Binding Works

When you bind a new authentication method to your account:

1. You must be logged in with an existing authentication method
2. You authenticate with the new method you want to bind (e.g., sign in with Google, verify email, connect external wallet)
3. The new authentication method is linked to your existing account
4. You can now use any of your bound authentication methods to access the same account

#### Benefits of Account Binding

* **Redundancy**: If you lose access to one authentication method, you can still access your account using another bound method
* **Flexibility**: Switch between authentication methods based on convenience or device availability
* **Migration**: Gradually migrate from one authentication method to another without losing access to your wallets
* **Security**: Multiple authentication methods provide additional security layers

#### Binding Restrictions

* Each authentication method can only be bound to one Clique Wallet account
* You cannot bind an authentication method that is already bound to another account
* You cannot bind the same authentication method twice to your account


# Transaction Signing

Clique Wallet provides secure transaction signing for all supported blockchain networks. All signing operations occur within the TEE, ensuring private keys never leave the secure enclave.

#### Supported Signing Methods

**EVM-Compatible Chains:**

* EIP-712 structured data signing for typed transactions
* Standard message signing for arbitrary data
* Transaction signing for Ethereum and EVM-compatible chains

**Solana:**

* Native Solana transaction signing
* Message signing for Solana applications
* Support for Solana's transaction format and instruction sets

**Hyperliquid:**

* Native HyperCore transaction signing, using EIP-712 structured data signing for typed transactions

#### Signing Process

1. **Prepare Transaction**: Your application prepares the transaction data according to the blockchain's requirements
2. **Request Signature**: Send the transaction data to Clique Wallet's signing endpoint
3. **TEE Signing**: The transaction is signed within the TEE's secure enclave
4. **Return Signature**: Only the signature is returned—the private key remains protected
5. **Submit Transaction**: Your application submits the signed transaction to the blockchain network

#### Security During Signing

* All signing operations require user authentication through a valid session or API key
* All signing operations occur within the TEE's hardware-protected enclave
* Private keys are never exposed in plaintext during the signing process
* Address verification ensures transactions are signed by the correct wallet
* Transaction validation can be enabled to verify transaction parameters before signing

#### Whitelist Signing

Clique Wallet supports whitelist signing, allowing you to restrict which transactions can be signed. This provides an additional layer of security by ensuring that only approved transactions are processed, protecting against unauthorized or malicious transaction attempts.

**How Whitelist Signing Works:**

* **Transaction Filtering**: When whitelist signing is enabled, only transactions that match the configured whitelist criteria are allowed to be signed
* **Flexible Configuration**: Whitelists can be configured based on various transaction parameters such as recipient addresses, contract addresses, transaction types, or other criteria
* **Automatic Rejection**: Any transaction that doesn't match the whitelist is automatically rejected before signing, preventing unauthorized operations

**Use Cases:**

* **Enterprise Security**: Restrict signing to only approved addresses or contracts, ensuring compliance with organizational policies
* **Risk Management**: Limit transactions to trusted recipients or protocols, reducing exposure to malicious contracts or phishing attempts
* **Operational Control**: Maintain strict control over which operations can be performed, especially for high-value accounts or automated systems

Whitelist signing is an optional security feature that can be configured when needed to provide additional protection for your wallets and assets.


# Parameter-Based Transaction Building

Instead of passing complete transaction objects, Clique Wallet supports building transactions from parameters. This approach provides full control over transaction construction and ensures transaction validity before signing.

#### How It Works

* **Parameter Input**: Provide transaction parameters (e.g., recipient address, amount, token address, decimals) instead of a complete transaction object
* **Server-Side Construction**: Clique Wallet constructs the transaction server-side, ensuring all parameters are valid and properly formatted
* **Automatic Validation**: All transaction parameters are validated before construction, preventing invalid or malformed transactions
* **Gas Estimation**: Gas limits and fees are automatically estimated and set correctly based on current network conditions
* **TEE Signing**: The constructed transaction is signed within the TEE and returned as a ready-to-submit raw transaction

#### Benefits

* **Enhanced Security**: Server-side construction ensures transactions are built correctly and cannot be tampered with
* **Simplified Integration**: No need to construct complex transaction objects—simply provide the necessary parameters
* **Automatic Optimization**: Gas estimation and fee calculation are handled automatically, ensuring optimal transaction parameters
* **Error Prevention**: Invalid parameters are caught before transaction construction, preventing failed transactions

#### Example Use Cases

* **Transfer Transactions**: Build transfer transactions by providing recipient address, amount, token address (optional for native transfers), and decimals
* **Contract Interactions**: Build contract interaction transactions by providing contract address, function parameters, and transaction data
* **Complex Operations**: Build multi-step operations like vault deposits, approvals, or redeems using structured parameter sets

Parameter-based transaction building works seamlessly with whitelist signing, providing comprehensive security and control over your wallet operations.


# API Keys and Programmatic Access

Clique Wallet provides comprehensive programmatic access through API keys, enabling automated operations and integration with external systems.

#### API Key Permissions

API keys support granular permission scopes:

* **View (1)**: Read-only access to account information, wallet addresses, and transaction history
* **View + Trading (3)**: View permissions plus the ability to execute trading operations
* **View + Transfer (5)**: View permissions plus the ability to transfer assets
* **View + Trading + Transfer (7)**: Full access to all operations

Permissions are enforced at the API level, ensuring that operations requiring specific permissions are blocked if the API key doesn't have the necessary access.

#### IP Whitelisting

API keys can be configured with IP address whitelists, restricting usage to specific IP addresses. This provides an additional layer of security for sensitive operations. IP whitelisting is optional and can be configured when creating or updating an API key.

#### API Key Management

Users can manage their API keys through authenticated endpoints:

* **Create**: Generate new API keys with specific permissions and IP whitelists
* **List**: View all API keys associated with the account
* **Activate/Deactivate**: Temporarily disable API keys without deleting them
* **Delete**: Permanently remove API keys

**Important**: API keys are only displayed once during creation. If you lose an API key, you must create a new one.


# Export Private Keys

Clique Wallet provides a secure export functionality that allows users to export their private keys, ensuring users maintain full control and ownership of their assets.

#### Export Process

The export process uses a two-step verification mechanism:

1. **Initiate Export**: Request to start the export process, which generates verification information
2. **Complete Export**: Provide the verification information to complete the export and receive the private keys

This two-step process ensures that only authenticated users can export their keys and prevents unauthorized access.

#### After Export

Once a user exports their private keys:

* The account is marked as exported
* **By default**, Clique Wallet will no longer sign transactions for exported accounts
* Users can still view their account information
* This is the default security measure to prevent unauthorized use after export

**Re-enabling Signing After Export:**

If necessary, signing can be enabled even after exporting private keys. However, it's important to note that in this case, the private keys are not as secure as before. Since the private keys have already been exported and are outside the TEE, Clique Wallet cannot ensure the same strict security guarantees as when keys remain exclusively within the TEE. Users should carefully consider the security implications before re-enabling signing for exported accounts.

#### Export Use Cases

* **Migration**: Move wallets to another service or self-custody solution
* **Backup**: Create a backup of private keys for disaster recovery
* **Self-Custody**: Transition to full self-custody while maintaining access to exported keys


# Account Management

Clique Wallet provides features for managing your account and personalizing your experience.

#### Account Information

Users can customize their account information:

* **Profile Customization**: Update account details as needed

#### Session Management

* **Active Sessions**: Sessions remain active while you use the application
* **Automatic Expiration**: Sessions expire after a period of inactivity for security
* **Re-authentication**: Simply log in again using any bound authentication method

#### Account Deletion

Users can permanently delete their accounts and all associated data. This requires that the user has already exported their private keys, ensuring users maintain control over their assets before account deletion.


# Security

Overview

Security is fundamental to Clique Wallet's architecture. We are a custodial wallet service, but it's important to understand that private keys are technically controlled and secured by the **Trusted Execution Environment (TEE)**. This design ensures that even our own development and operations team cannot access user private keys, effectively protecting user key security.

#### Security Architecture

Clique Wallet implements a multi-layered security architecture:

* **TEE Protection**: All critical processes—including key generation, storage, and transaction signing—run entirely within the TEE's encrypted memory. This ensures that sensitive data is never exposed in plaintext, making it inaccessible to any external parties and effectively preventing data theft.
* **Encrypted Storage**: All user data is encrypted before being stored. Only the TEE holds the encryption keys. Even if data is accessed at the database level, the actual sensitive information remains encrypted and unreadable.
* **Data Integrity Verification**: We apply integrity checks to all user data. Any attempt to tamper with the data by an attacker would be detected and rejected, ensuring the information remains authentic and unaltered.
* **End-to-End Encrypted Communication**: All data transmitted between the user and our services is protected via HTTPS encryption, preventing interception or leakage over the network.
* **Session Security**: Sensitive interfaces are protected with Http-Only session-based authentication. This mechanism helps safeguard user sessions from client-side attacks, enhancing security on the user's end.


# Threat Model

Clique Wallet's security architecture is designed to protect against a comprehensive range of threats:

* **Insider Threats**: Traditional custodial wallets are vulnerable to insider attacks where service operators or employees could potentially access user private keys. Clique Wallet mitigates this by ensuring all cryptographic operations occur within the TEE, making private keys inaccessible even to our own development and operations team.
* **External Attackers**: Malicious actors attempting to breach our systems cannot access private keys because they are never exposed outside the TEE's encrypted enclaves. Even if an attacker gains access to our servers or databases, encrypted data remains unreadable without the TEE's decryption keys.
* **Host OS and Cloud Provider Compromise**: Even if the host operating system is compromised or the cloud provider's infrastructure (such as Azure, GCP, or AWS) is breached, the TEE's hardware-protected enclaves remain secure. The TEE creates an isolated execution environment that is cryptographically protected from the host OS, hypervisor, and cloud provider, ensuring that private keys remain inaccessible even in the event of a complete system compromise.
* **Software Vulnerabilities**: Software bugs, zero-day exploits, or compromised dependencies could potentially expose sensitive data in traditional systems. Clique Wallet's TEE-based architecture isolates cryptographic operations from the rest of the system, ensuring that software vulnerabilities in non-critical components cannot compromise private keys.
* **Network Attacks**: Man-in-the-middle attacks, packet interception, or network-based exploits are mitigated through end-to-end HTTPS encryption. All communications between users and Clique Wallet services are encrypted, preventing attackers from intercepting or tampering with data in transit.
* **Database Breaches**: Even if an attacker successfully breaches our database, all sensitive user data is encrypted at rest. Without access to the TEE's encryption keys, the stolen data remains cryptographically protected and unusable.
* **Client-Side Attacks**: Cross-site scripting (XSS) attacks or malicious browser extensions cannot access session tokens or authentication credentials due to Http-Only session cookies and secure session management practices.
* **Key Extraction Attempts**: Attempts to extract private keys through memory dumps, debugging, or reverse engineering are prevented by the TEE's hardware-level protection, which ensures keys never exist in plaintext outside the secure enclave.


# TEE & Intel SGX

#### **Trusted Execution Environment (TEE)**

The Trusted Execution Environment (TEE) is a secure, isolated area within the main processor that acts as a hardware-protected vault. TEE is a security technology standard that provides a secure area of execution within a processor, ensuring that code and data loaded inside are protected with respect to confidentiality and integrity. Unlike software-based security solutions that rely on operating system permissions or application-level encryption, TEE provides hardware-level isolation that protects code and data from unauthorized access at the CPU level. TEE implementations create isolated execution environments where sensitive operations can be performed securely, even when the host operating system, hypervisor, or other system components are compromised.

TEE technology addresses a critical security challenge known as the "trust boundary" problem. In traditional systems, any code running with sufficient privileges can access all memory and data, meaning users must trust not just the application, but also the OS, hypervisor, cloud provider, and all software in between. TEE eliminates this trust dependency by creating a hardware-enforced trust boundary that even the most privileged software cannot cross.

For custodial wallet services like Clique Wallet, TEE is particularly valuable because it allows the service to manage user wallets (providing convenience) while ensuring that private keys remain inaccessible even to the service operators themselves (providing security). This hardware-level protection is fundamental to Clique Wallet's security model, ensuring that sensitive cryptographic operations are protected at the silicon level rather than relying solely on software safeguards, or trust in system administrators.

#### **Intel SGX  (Software Guard Extensions)**&#x20;

Intel SGX (Software Guard Extensions) is Intel's implementation of TEE technology and is widely used in production environments across various industries. SGX provides a set of CPU instructions that allow applications to create protected areas of memory called **Enclave**. SGX creates encrypted memory enclaves—isolated regions of memory that are cryptographically protected. Code and data within an SGX enclave are encrypted using keys derived from the CPU itself, and can only be decrypted by the CPU when executing within that specific enclave. This encryption happens transparently at the hardware level, meaning that even if an attacker has root access to the system, physical access to the server, or control over the hypervisor, they cannot read or modify the contents of an SGX enclave.

SGX enclaves operate through a hardware-based security model. When an enclave is created, the CPU allocates a protected region of memory (EPC - Enclave Page Cache) that is encrypted using keys stored within the CPU's secure key hierarchy. The enclave's memory pages are encrypted with a unique key derived from the CPU's root key, the enclave's measurement (cryptographic hash of code and data), and the enclave's identity. The CPU automatically decrypts data when it enters the enclave and re-encrypts it when it leaves, all at the hardware level without exposing plaintext to any software layer.

SGX provides cryptographic attestation capabilities that allow verification that code is running in a genuine SGX enclave on an authentic Intel processor. The enclave generates a cryptographic report signed by the CPU, which can be verified remotely through Intel's Attestation Service to confirm the enclave is running expected code on a genuine processor. Enclaves can also "seal" data (encrypt it) using keys derived from the enclave's identity and the CPU, allowing sealed data to persist securely across system reboots.

Clique Wallet leverages Intel SGX to protect all critical cryptographic operations. Private keys are generated entirely within an SGX enclave, stored in encrypted form using SGX's sealing mechanism, and used for transaction signing without ever leaving the enclave in plaintext. When signing transactions, only the signature is returned—the private key remains sealed within the enclave. All key derivation operations for sub-wallets also occur within the enclave, ensuring derived keys are equally protected. This multi-layered protection (hardware, enclave, and application levels) ensures private keys remain secure even when the host OS is compromised, cloud providers have system access, or attackers gain root privileges.


# Data Protection & Encryption

Clique Wallet implements comprehensive data protection through multiple layers of encryption, ensuring that sensitive information remains secure in use, at rest, and in transit.

#### Encryption in Use

All critical cryptographic operations in Clique Wallet are performed within the TEE's hardware-protected enclaves. When private keys are generated, stored, or used for transaction signing, they exist only in encrypted form within the TEE's secure memory. The TEE ensures that private keys are never exposed in plaintext, even during active use. This hardware-level encryption protects keys from being accessed by the host operating system, hypervisor, cloud provider infrastructure, or any other software running on the system.

The TEE's encryption operates transparently at the CPU level, automatically encrypting data when it enters the enclave and decrypting it only within the secure execution environment. This means that even if an attacker gains root access to the system, performs memory dumps, or attempts to extract keys through debugging, the private keys remain cryptographically protected and inaccessible outside the TEE.

#### Encryption at Rest

All sensitive user data stored in Clique Wallet's databases is encrypted before being persisted. This includes user wallet information, API keys, session data, and other sensitive records. The encryption uses industry-standard algorithms that provide both confidentiality and authenticity.

The encryption architecture uses a hierarchical key management system where encryption keys are securely managed and stored within the TEE. Different types of data use separate encryption keys, ensuring that a compromise of one data type does not affect others. Each encryption operation uses cryptographically secure random values to ensure that identical data produces different ciphertext, preventing pattern analysis attacks.

The encryption system includes built-in data integrity verification, which means any attempt to tamper with encrypted data will be detected during decryption. Even if an attacker gains access to the database, the encrypted data remains unreadable without access to the encryption keys, which are protected within the TEE.

#### Encryption in Transit

All communications between users and Clique Wallet services are protected using **HTTPS (TLS/SSL)** encryption. This ensures that:

* Data transmitted over the network cannot be intercepted or read by third parties
* Man-in-the-middle attacks are prevented through certificate validation
* Data integrity is maintained during transmission
* Authentication between client and server is cryptographically verified

Clique Wallet uses strong TLS configurations with modern cipher suites, ensuring that all network traffic is encrypted with industry-standard protocols. This protection extends to all API endpoints, authentication flows, and data synchronization operations.


# Authentication & Authorization

Clique Wallet implements a comprehensive authentication and authorization system that supports multiple authentication methods for users while providing secure programmatic access through API keys with fine-grained permission controls.

#### User Authentication

Clique Wallet supports a wide range of authentication methods, allowing users to access their wallets through their preferred method:

* **Social OAuth**: Users can authenticate using social media accounts including Google, X/Twitter, and Telegram. OAuth flows use PKCE (Proof Key for Code Exchange) for enhanced security, ensuring that authorization codes cannot be intercepted and reused by attackers.
* **Email and Phone Verification**: Users can authenticate using email addresses or phone numbers. The system sends a verification code to the provided email or phone number, which must be verified during login. This two-factor verification process ensures that only users with access to the registered contact method can access the account.
* **Apple Sign-In**: Native support for Apple's Sign-In service, providing seamless authentication for users on Apple devices.
* **External Wallet Connections**: Users can authenticate by connecting existing external wallets including MetaMask, Phantom, Okx, Rabby, Coinbase Wallet, and WalletConnect. This authentication method uses a challenge-response mechanism where users sign a challenge message with their external wallet, proving ownership without exposing private keys.
* **Account Binding**: Users can bind multiple authentication methods to a single Clique Wallet account. This allows flexible access—users can log in using any of their bound authentication methods while maintaining access to the same wallets and assets. Account binding is particularly useful for users who want to maintain multiple ways to access their account or who migrate from one authentication method to another.

All authentication methods are validated server-side, and upon successful authentication, Clique Wallet automatically creates wallets for all supported blockchains if they don't already exist. The authentication process ensures that users can only access accounts they own, and all authentication credentials are verified cryptographically or through trusted third-party providers.

#### Session Management

User-facing applications use secure HTTP-only session cookies for authentication. This approach provides several security benefits:

* **HTTP-Only Cookies**: Session cookies are marked as HTTP-only, preventing client-side JavaScript from accessing them. This protects against cross-site scripting (XSS) attacks where malicious scripts might attempt to steal session tokens.
* **Secure Cookies**: In production environments, session cookies are transmitted only over HTTPS connections, ensuring that session tokens cannot be intercepted over unencrypted networks.
* **Session Expiration**: Sessions automatically expire after a period of inactivity, reducing the risk of unauthorized access if a user's device is compromised. Users must re-authenticate after session expiration.
* **Same-Site Protection**: Session cookies use SameSite protection to prevent cross-site request forgery (CSRF) attacks, ensuring that cookies are only sent with requests originating from the same site.

Session data is stored securely and encrypted, with session keys derived from the TEE-protected master key. This ensures that even if session data is accessed, it cannot be decrypted without access to the TEE.

#### API Key Authentication

For programmatic access, Clique Wallet provides API key authentication. API keys enable automated operations, trading bots, and other programmatic use cases while maintaining security through multiple layers of protection:

* **Bearer Token Authentication**: API keys are provided as Bearer tokens in the Authorization header of HTTP requests. The format follows the standard `Authorization: Bearer <api_key>` pattern.
* **API Key Structure**: API keys are cryptographically secure and include both a unique identifier and a random component. The full key is only displayed once during creation, after which only a prefix is shown for identification purposes.
* **Encrypted Storage**: API keys are encrypted at rest and include integrity verification. This ensures that even if an attacker gains database access, the API keys cannot be revealed, replaced, or otherwise compromised through tampering attacks.
* **Key Validation**: Each API key request is validated for authenticity, active status, expiration, and IP whitelisting (if configured). Invalid, inactive, expired, or unauthorized IP requests are immediately rejected.

Together, these authentication and authorization mechanisms ensure that only authorized users and applications can access Clique Wallet accounts and perform operations, while providing flexibility for different use cases and security requirements.


# Compliance

Clique Wallet is designed with compliance and regulatory considerations in mind, implementing security practices and controls that align with industry standards and best practices for custodial wallet services.

#### Security Standards

Clique Wallet's security architecture follows industry best practices for protecting sensitive financial data and cryptographic assets. The use of hardware-level security through TEE technology provides a foundation that exceeds many software-based security implementations, ensuring that private keys and sensitive data are protected at the silicon level.

The multi-layered security approach—combining TEE protection, encryption at rest and in transit, data integrity verification, and comprehensive access controls—creates a defense-in-depth strategy that addresses multiple security requirements simultaneously.

#### Data Protection

Clique Wallet implements comprehensive data protection measures that align with data protection regulations and privacy standards. All user data is encrypted, and the architecture ensures that sensitive information cannot be accessed by unauthorized parties, including service operators. This approach provides strong privacy protections while maintaining the functionality required for wallet operations.

The TEE-based architecture ensures that even in the event of data breaches or system compromises, private keys and sensitive user data remain cryptographically protected and inaccessible to attackers.

#### Security Audits

Clique Wallet's security architecture is designed to be auditable and verifiable. The use of Intel SGX provides cryptographic attestation capabilities, including **remote attestation**, that allow verification that code is running in a genuine TEE environment on authentic Intel processors. Remote attestation enables third parties to cryptographically verify the integrity and authenticity of the TEE enclave remotely, without requiring physical access to the system.

This remote attestation capability enables third-party security audits and assessments to verify the security properties of the system, ensuring that the TEE is running the expected code and that the hardware protection is functioning correctly.

Regular security assessments and audits help ensure that Clique Wallet maintains the highest security standards and identifies potential improvements to the security posture.

#### Regulatory Considerations

As a custodial wallet service, Clique Wallet is designed with regulatory compliance in mind. The architecture ensures that private keys remain inaccessible to service operators, addressing concerns about custodial control while providing the convenience benefits of custodial services.

The security controls, data protection measures, and audit capabilities built into Clique Wallet's architecture support compliance with various regulatory frameworks and industry standards that may apply to digital asset custody and wallet services.


# SDK & API Reference

Clique Wallet provides comprehensive SDK and API support for developers to integrate wallet functionality into their applications. Whether you're building a web application, mobile app, or backend service, Clique Wallet offers flexible integration options to meet your needs.

### Overview

The Clique Wallet SDK and API enable developers to:

* **Authenticate Users**: Integrate various authentication methods including social OAuth, email/phone verification, and external wallet connections
* **Manage Wallets**: Create and manage multiple wallets across different blockchain networks
* **Sign Transactions**: Securely sign transactions for all supported chains within the TEE
* **Build Transactions**: Construct transactions from parameters with automatic validation and gas estimation
* **Manage API Keys**: Create and manage API keys for programmatic access with granular permissions
* **Handle Account Operations**: Manage user accounts, bind authentication methods, and handle account lifecycle

### Integration Options

Clique Wallet supports multiple integration approaches:

* **JavaScript/TypeScript SDK**: NPM package for web and Node.js applications
* **RESTful API**: HTTP-based API for any programming language or platform

### Documentation Status

The detailed SDK and API documentation is currently being developed and will be available soon.


# FAQ

**Is Clique Wallet a custodial wallet?**

Yes, Clique Wallet is a custodial wallet service. It is important to note that the private keys are technically controlled and secured by the Trusted Execution Environment (TEE). This design ensures that even our own development and operations team cannot access user private keys, effectively protecting user key security.

**How is Clique Wallet different from other wallet solutions?**

Clique Wallet combines the convenience of custodial wallets with the security guarantees of self-custodial solutions. Traditional custodial wallets require users to trust service operators with their private keys, while self-custodial wallets require users to manage complex seed phrases. Clique Wallet eliminates this trade-off by using hardware-level security (TEE) to ensure that even service operators cannot access user private keys, while maintaining a frictionless user experience.

**What blockchains does Clique Wallet support?**

Clique Wallet supports Solana, EVM-compatible chains (including Ethereum, Base, Arbitrum, BNB Smart Chain, HyperEVM, and more), and Hyperliquid (both HyperEVM and HyperCore). The architecture is extensible and can support additional blockchain networks as they gain adoption.

**What authentication methods are supported?**

Currently, Clique Wallet supports multiple authentication methods:

* Social OAuth (Google, X/Twitter, Telegram, Apple)
* Email and Phone verification
* External wallet connections (MetaMask, Phantom, Okx, Rabby, Coinbase Wallet, WalletConnect)

In the future, we will support more authentication methods.

**Can I export my private keys?**

Yes, Clique Wallet provides a secure export functionality that allows users to export their private keys through a two-step verification process. This ensures users maintain full control and ownership of their assets, providing an escape hatch if needed.

**What happens if I lose access to my account?**

If you've bound multiple authentication methods to your account, you can use any of them to regain access. However, if you've lost access to all authentication methods, we cannot help you recover your account. This is because Clique Wallet's security architecture ensures that even service operators cannot access user accounts or private keys. It's strongly recommended to bind multiple authentication methods (e.g., email, social login, external wallet) to your account for redundancy and to prevent account loss.

**What happens if Clique Wallet's servers are compromised?**

Even if an attacker gains access to Clique Wallet's servers, databases, or cloud infrastructure, private keys remain protected. The TEE's hardware-protected enclaves are cryptographically isolated from the host operating system, hypervisor, and cloud provider. Encrypted data stored in databases cannot be decrypted without access to the TEE's encryption keys, which remain protected within the secure enclaves.

**Can Clique Wallet staff access my private keys?**

No. Clique Wallet's architecture ensures that private keys are controlled and secured by the Trusted Execution Environment (TEE). Even our own development and operations team cannot access user private keys. The TEE creates a hardware-enforced trust boundary that even the most privileged software cannot cross.


# Troubleshooting

**I didn't receive my verification code (email/phone)**

* Check your spam/junk folder for email verification codes
* Ensure your phone number is correctly formatted (including country code)
* Wait a few minutes and request a new code if needed
* Verify that the email address or phone number is correct

**My API key is not working**

* Verify that the API key is active (not deactivated)
* Ensure you're using the correct format: `Authorization: Bearer <api_key>`
* Verify that your IP address is whitelisted (if IP whitelisting is enabled)
* Check that the API key has the required permissions for the operation

**I lost my API key**

* API keys are only displayed once during creation and cannot be recovered
* You'll need to create a new API key through the API key management endpoints
* Delete or deactivate the old API key if you suspect it may have been compromised

**I can't sign a transaction**

* Ensure you're authenticated with a valid session
* Check that the wallet address exists and belongs to your account
* Verify that you're using the correct network (Solana, EVM-compatible, Hyperliquid)
* Ensure your account hasn't been exported

**My transaction failed**

* Verify that you have sufficient balance for the transaction (including gas fees)
* Check that the transaction parameters are correct (address, amount, network)
* Ensure your account hasn't been exported (exported accounts cannot sign transactions)
* Verify network connectivity and that the blockchain network is operational

**I can't see my wallet address**

* Wallets are automatically created upon first login
* Ensure you're logged in with a valid session
* Check that you're querying the correct network
* Verify that wallet creation completed successfully

**My wallet balance is incorrect**

* Wallet balances are read from the blockchain
* There may be a delay in balance updates
* Verify the balance directly on a blockchain explorer using your wallet address
* Check that you're looking at the correct network and wallet

**What happens after I export my keys?**

* After exporting, your account is marked as exported
* Clique Wallet will no longer sign transactions for exported accounts
* You can still view your account information, but transaction signing is disabled
* This is a security measure to prevent unauthorized use after export

**I'm getting a 401 Unauthorized error**

* Your session may have expired
* Verify that you're sending the correct authentication credentials
* For API requests, ensure your API key is valid and active
* Try logging out and logging back in

**I'm getting a 400 Bad Request error**

* Verify that your request parameters are correct
* Check that required fields are provided
* Ensure data formats are correct (e.g., addresses, amounts, network identifiers)
* Review the API documentation for the specific endpoint requirements

**I'm getting a 500 Internal Server Error**

* This indicates a server-side issue
* Wait a few moments and try again
* If the issue persists, contact support
* Check Clique Wallet's status page (if available) for service updates

**The service seems slow or unresponsive**

* Check your network connection
* Verify that the blockchain networks you're using are operational
* There may be network congestion affecting response times
* Try again after a few moments

#### Getting Help

If you continue to experience issues after trying the troubleshooting steps above, please contact Clique Wallet support with the following information:

* Description of the issue
* Steps to reproduce
* Error messages (if any)
* Your account information (without sensitive details)
* Timestamp of when the issue occurred


# Clique Pipelines SDK

The `Clique Pipelines SDK` is an open-source library that enables user to access `Clique Pipelines Data` easily and quickly. We currently support NodeJS and Web SDKs.

### Setup

#### NodeJS

Add the dependency:

```sh
pnpm add @cliqueofficial/clique-pipelines-sdk-node
# OR
yarn add @cliqueofficial/clique-pipelines-sdk-node
# OR 
npm install @cliqueofficial/clique-pipelines-sdk-node
```

Get the client instance:

```typescript
import { Client } from '@cliqueofficial/clique-pipelines-sdk-node';

const config = {
  // Whether the Pipelines Data is retrieved in a TEE environment.
  enableTee: true,
  // Clique Pipelines Data Service URL, 
  serviceUrl: 'https://pipelines-server.sit.clique-test.tech',
};
const client = new Client(config);
```

#### Web

Add the dependency:

```sh
pnpm add @cliqueofficial/clique-pipelines-sdk-web
# OR
yarn add @cliqueofficial/clique-pipelines-sdk-web
# OR 
npm install @cliqueofficial/clique-pipelines-sdk-web
```

Get the client instance:

```typescript
import { Client } from '@cliqueofficial/clique-pipelines-sdk-web';

const config = {
  // Whether the Pipelines Data is retrieved in a TEE environment.
  enableTee: true,
  // Clique Pipelines Data Service URL, 
  serviceUrl: 'https://pipelines-server.sit.clique-test.tech',
};
const client = new Client(config);
```

### Pipelines

{% hint style="info" %}
We currently only support the data available through the official platform APIs. If you wish to access more private pipeline data from users, please use our [Clique Browser Extension](/toolchain/clique-browser-extension).
{% endhint %}

#### Common Types

* `Response`

```typescript
interface Response {
   id: number;
   attestation?: {
     id: string;
     type: 'SGX';
     isvEnclaveQuoteBody: string;
   };
   signature?: string;
   result: Record<string, any>; 
}
```

The `attestation` and `signature` will be `undefined` if you disable `TEE`.

#### Twitter

* `userInfo`

```typescript
interface TwitterUserInfo {
  idStr: string;
  name: string;
  screenName: string;
  profileImageUrlHttps: string;
  description: string;
  fastFollowersCount: number;
  favouritesCount: number;
  followersCount: number;
  friendsCount: number;
  mediaCount: number;
  statusesCount: number;
  createdAt: string;
  isBlueVerified: boolean;
}

const oauthAccessToken = 'xxxxxx';
const response: Response = await client.twitter.userInfo(oauthAccessToken);
const userInfo = response.result[response.id]; // TwitterUserInfo
```

#### Steam

* `userInfo`

```typescript
export interface SteamUserInfo {
  steamId: string;
  communityVisibilityState: number;
  profileState: number;
  personaName: string;
  profileUrl: string;
  lastLogOff: number;
  timeCreated: number;
  personaState: number;
  locCountryCode: string;
}
const steamId = 'xxxxxx';
const response: Response = await client.steam.userInfo(steamId);
const userInfo = response.result[response.id]; // SteamUserInfo
```

* `listBadge`

```typescript
interface SteamBadges {
  badges: {
    badgeId: number;
    completionTime: number;
    level: number;
    scarcity: number;
    xp: number;
  }[];
}

const steamId = 'xxxxxx';
const response: Response = await client.steam.listBadges(steamId);
const badges = response.result[response.id].badges; // SteamBadges
```

* `userOwnedGames`

```typescript
export interface SteamPlayerOwnedGame {
  appId: string;
  name: string;
  playtimeForever: number;
  imgIconUrl: string;
  hasCommunityVisibleStats: boolean;
  playtimeWindowsForever: number;
  playtimeMacForever: number;
  playtimeLinuxForever: number;
  playtimeDeckForever: number;
  rtimeLastPlayed: number;
  playtimeDisconnected: number;
}

export interface SteamUserOwnedGames {
  games: SteamPlayerOwnedGame[];
  gameCount: number;
}
const steamId = 'xxxxxx';
const response: Response = await client.steam.userOwnedGames(steamId);
const userOwnedGames = response.result[response.id]; // SteamUserOwnedGames
```

* `gameStats`

```typescript
interface SteamGameStatsRequest {
  // how many top data
  top?: number;
}

export interface SteamGameStats {
  sumMoneySpentOnGames: number;
  listCategory: {
    gameId: number;
    category: string[];
  }[];
  sumHoursPlayed: string;
  sumOwnedGames: number;
  topPlayedGames: {
    gameId: number;
    name: string;
    hours: string;
  }[];
  gamePlayedTime: {
    name: string;
    time: number;
  }[];
  topGenresByHours: {
    name: string;
    hours: string;
  }[];
  topCategoriesByHours: {
    name: string;
    hours: string;
  }[];
  ownedGameNames: string[];
  userGameAchievements: {
    steamId: string;
    gameName: string;
    achievements: {
      apiName: string;
      name: string;
      achieved: boolean;
      unlockTime: number;
      description: string;
    }[];
  }[];
  sumAchievedAchievement: number;
}

const steamId = 'xxxxxx';
const request: SteamGameStatsRequest = {};
const response: Response = await client.steam.gameStats(steamId, request);
const gameStats = response.result[response.id]; // SteamGameStats
```

#### Discord

* `userInfo`

```typescript
interface DiscordUserInfo {
  id: string;
  username: string;
  discriminator: string;
  publicFlags: number;
  flags: number;
  globalName: string;
  mfaEnabled: boolean;
  locale: string;
  premiumType: number;
  createdAt: number;
}
const oauthAccessToken = 'xxxxxx';
const response: Response = await client.discord.userInfo(oauthAccessToken);
const userInfo = response.result[response.id]; // DiscordUserInfo
```

* `isMemberOf`

```typescript
interface DiscordIsMemberOf {
  isMemberOf: boolean;
}
const botToken = 'xxxxxx';
const serverId = 'xxxxxx';
const uid = 'xxxxxx';
const response: Response = await client.discord.isMemberOf({
  botToken, serverId, uid,
});
const isMemberOf = response.result[response.id].isMemberOf;
```

* `timeJoined`

```typescript
interface DiscordTimeJoined {
  joinedAt: number;
}
const botToken = 'xxxxxx';
const serverId = 'xxxxxx';
const uid = 'xxxxxx';
const response: Response = await client.discord.timeJoined({
  botToken, serverId, uid,
});
const timeJoined = response.result[response.id].joinedAt;
```

* `numInvites`

```typescript
interface DiscordNumInvites {
  numInvites: number;
}
const botToken = 'xxxxxx';
const serverId = 'xxxxxx';
const uid = 'xxxxxx';
const response: Response = await client.discord.numInvites({
  botToken, serverId, uid,
});
const numInvites = response.result[response.id].numInvites;
```

* `userRoles`

```typescript
interface DiscordUserRoles {
  roles: string[];
}
const botToken = 'xxxxxx';
const serverId = 'xxxxxx';
const uid = 'xxxxxx';
const response: Response = await client.discord.userRoles({
  botToken, serverId, uid,
});
const userRoles = response.result[response.id].userRoles;
```

#### GitHub

* `userInfo`

```typescript
interface GithubUserInfo {
  id: number;
  name: string;
  login: string;
}
const oauthAccessToken = 'xxxxxx';
const response: Response = await client.github.userInfo(oauthAccessToken);
const userInfo = response.result[response.id]; // GithubUserInfo
```

* `stats`

```typescript
interface GithubStats {
  name: string;
  login: string;
  followers: number;
  totalPRs: number;
  totalCommits: number;
  totalIssues: number;
  totalStars: number;
  contributedTo: number;
}
const oauthAccessToken = 'xxxxxx';
const response: Response = await client.github.stats(oauthAccessToken);
const stats = response.result[response.id]; // GithubStats
```

#### Spotify

* `userInfo`

```typescript
interface SpotifyUserInfo {
  id: number;
  country: string;
  displayName: string;
  followers: number;
  email: string;
}
const oauthAccessToken = 'xxxxxx';
const response: Response = await client.spotify.userInfo(oauthAccessToken);
const userInfo = response.result[response.id]; // SpotifyUserInfo
```

* `topTracks`

```typescript
interface SpotifyTopTracksStats {
  top10Artists: string[];
  top10Genres: string[];
  topTracks: string[];
}
const oauthAccessToken = 'xxxxxx';
const response: Response = await client.spotify.topTracks(oauthAccessToken);
const topTracks = response.result[response.id]; // SpotifyTopTracksStats
```

* `followedArtists`

```typescript
interface SpotifyArtist {
  id: string;
  genres: string[];
  name: string;
  imageUrl: string;
}
interface SpotifyFollowedArtists {
  artists: SpotifyArtist[];
}
const oauthAccessToken = 'xxxxxx';
const response: Response = await client.spotify.followedArtists(oauthAccessToken);
const followedArtists = response.result[response.id]; // SpotifyFollowedArtists
```

* `recentPlayedTracks`

```typescript
interface SpotifyTrack {
  id: string;
  name: string;
}
interface SpotifyRecentPlayedTrack {
  tracks: SpotifyTrack[];
}
const oauthAccessToken = 'xxxxxx';
const response: Response = await client.spotify.recentPlayedTracks(oauthAccessToken);
const recentPlayedTracks = response.result[response.id]; // SpotifyRecentPlayedTrack[]
```


# Clique Attestation SDK

Attestations are like digital records that act as proof or a stamp of approval on information provided by one party about pretty much anything. In our case attestations are statements made by an issuer-node about a subject. The subject can be an EVM address, or a VC, or an IPFS hash, or even another attestation.

We use attestations because they are versatile and designed for composability and interoperability, they can vouch for a multitude of information types.

Some great documentation has been done already by our friends over at [EAS](https://docs.attest.sh/docs/welcome) and [Verax](https://docs.ver.ax/verax-documentation/).


# Attestation Protocols

We are integrated with the two biggest attestation protocols. EAS (Ethereum-Attestation-Service) is backed by a strong team building a strong narrative and use case around attestations. Verax is a community driven community first open source protocol which offers strong standardisation but also flexibility for the needs of projects.

If you are interested in attestations we strongly advise you to check out both projects. The easiest way to get started is exploring attestations through the explorers.

EAS - <https://easscan.org/>\
Verax - <https://explorer.ver.ax/linea>


# Reading Attestations On-chain

This step-by-step guide will run you through reading attestations onchain by looking at an example of a uniswap-v4 hook.

Full code can be found [here](https://github.com/CliqueOfficial/attestation-hooks/blob/bf765a494b4d91f5e5ab252c6a72109be52a40fe/src/AttestationHook.sol#L4).

More info on V4 hooks [here](https://blog.uniswap.org/uniswap-v4).

In this example we are going to look at a hook; which checks for an attestation value (boolean in this example). Only holders of attestations with a value of true will be allow to swap using this hook. For this example, we are going to be interested in looking at the beforeSwap hook.

When working with Clique's onchain attestations SDK, the first step is to configure which type of attestations we are working with.

```solidity
/**
 * One way is to define 2 attestation types, 
 * one for EAS and one Verax attestations
 */
enum AttestationType {
    EAS,
    VERAX
}
```

```solidity
bytes32 _easSchema = 0x000..;
bytes32 _veraxSchema = 0x00..;
```

Now we can define functions for retrieving attestations from users performing swaps. In this example we will define a function for EAS and a function Verax. For more detail, you can check the implementation of the Connector smart contract [here](https://github.com/CliqueOfficial/attestor-contracts).

```solidity
/**
 * @dev Function to get the EAS attestation value.
 * @return The EAS attestation vamue.
 */
function _easAttestation() internal view returns (bytes memory) {
    bytes32 attestationId = _connector.getReceivedAttestationUIDs(
        tx.origin,
        _easSchema,
        0,
        1,
        false
    )[0];

    return
        _connector.getAttestationValueById(
            _connector.EAS(),
            attestationId
        );
}

/**
 * @dev Function to get the Verax attestation value.
 * @return The Verax attestation value.
 */
function _veraxAttestation() internal view returns (bytes memory) {
    bytes32 attestationId = _connector.getReceivedAttestationUIDs(
        tx.origin,
        _veraxSchema,
        0,
        1,
        false
    )[0];

    return
        _connector.getAttestationValueById(
            _connector.VERAX(),
            attestationId
        );
}
```

After choosing a schema, the schemaId is stored as a variable.  In our case, our shema type definition is just a boolean. So we can simply decode the attestation value into a boolean and check that the result is "true" in the beforeSwap function.

```solidity
bytes32 _easSchema = 0x000..;
bytes32 _veraxSchema = 0x00..;

/**
 * @dev Function to be called before a swap. Performs attestation checks.
 * @return The selector of the beforeSwap function.
 */
function beforeSwap(
    address,
    PoolKey calldata,
    IPoolManager.SwapParams calldata,
    bytes calldata
) external view override returns (bytes4) {
    bytes memory value = _attestationType == AttestationType.EAS
        ? _easAttestation()
        : _veraxAttestation();

    if (abi.decode(value, (bool)) != true) revert AttestationNotValid();

    return BaseHook.beforeSwap.selector;
}
```

We now have all that we need to read attestations onchain inside a Uniswap V4 hook. The code explored in the guide is below, and the full smart contract can be found in the gihtub repo.

```solidity
/**
 * @dev Enum to represent the type of attestation.
 */
enum AttestationType {
    EAS,
    VERAX
}

bytes32 _easSchema = 0x000..;
bytes32 _veraxSchema = 0x00..;

/**
 * @dev Function to be called before a swap. Performs attestation checks.
 * @return The selector of the beforeSwap function.
 */
function beforeSwap(
    address,
    PoolKey calldata,
    IPoolManager.SwapParams calldata,
    bytes calldata
) external view override returns (bytes4) {
    bytes memory value = _attestationType == AttestationType.EAS
        ? _easAttestation()
        : _veraxAttestation();

    if (abi.decode(value, (bool)) != true) revert AttestationNotValid();

    return BaseHook.beforeSwap.selector;
}

/**
 * @dev Function to get the EAS attestation value.
 * @return The EAS attestation vamue.
 */
function _easAttestation() internal view returns (bytes memory) {
    bytes32 attestationId = _connector.getReceivedAttestationUIDs(
        tx.origin,
        _easSchema,
        0,
        1,
        false
    )[0];

    return
        _connector.getAttestationValueById(
            _connector.VERAX(),
            attestationId
        );
}

/**
 * @dev Function to get the Verax attestation value.
 * @return The Verax attestation value.
 */
function _veraxAttestation() internal view returns (bytes memory) {
    bytes32 attestationId = _connector.getReceivedAttestationUIDs(
        tx.origin,
        _veraxSchema,
        0,
        1,
        false
    )[0];

    return
        _connector.getAttestationValueById(
            _connector.VERAX(),
            attestationId
        );
}
```


# Reading Attestations Off-Chain

This step-by-step guide will run you through programatically reading attestations offchain using Typescript SDKs for EAS and Verax protocols.

### Verax

Find the full Verax SDK documentation [here](https://docs.ver.ax/verax-documentation/developer-guides/using-the-sdk).

Start by installing the Verax SDK package.

```sh
# npm
npm i --save @verax-attestation-registry/verax-sdk
```

Next create a typescript file in a node project and paste the following code.

```typescript
// ES6
import { VeraxSdk } from "@verax-attestation-registry/verax-sdk";

const veraxSdk = new VeraxSdk(VeraxSdk.DEFAULT_LINEA_TESTNET_FRONTEND);

const attestationDataMapper = veraxSdk.attestation; // RW Attestations

const myAttestation = await attestationDataMapper.findOneById("0x000000000000000000000000000000000000000000000000000000000000109b");

// args:
// 	- criteria: object {property1: value1, property2: value2, ...}
// 	- page: integer (optional, default 0)
// 	- offset: integer (optional, default 50, max= 500)
// 	- orderBy: string (optional, default createdAt)
// 	- order(property?): enum string "ASC", "DESC" (optional, default "DESC")
//
const myAttestations = await attestationDataMapper.findBy(
  { portalId: "37773", subject: "John" },
  4,
  30,
  "schemaId",
  "ASC",
);

console.log(myAttestations);
```

### EAS

Find the full EAS SDK documentation [here](https://docs.attest.sh/docs/developer-tools/eas-sdk).

Start by installing the EAS SDK package.

```typescript
npm install @ethereum-attestation-service/eas-sdk
```

Next create a typescript file and paste in the following code

```typescript
import { EAS } from "@ethereum-attestation-service/eas-sdk";
import { EAS, Offchain, SchemaEncoder, SchemaRegistry } from "@ethereum-attestation-service/eas-sdk";
import { ethers } from 'ethers';

export const EASContractAddress = "0xC2679fBD37d54388Ce493F1DB75320D236e1815e"; // Sepolia v0.26

// Initialize the sdk with the address of the EAS Schema contract address
const eas = new EAS(EASContractAddress);

// Gets a default provider (in production use something else like infura/alchemy)
const provider = ethers.providers.getDefaultProvider(
  "sepolia"
);

// Connects an ethers style provider/signingProvider to perform read/write functions.
// MUST be a signer to do write operations!
eas.connect(provider);

// The UID of the attestation we want to fetch
const uid = "0xff08bbf3d3e6e0992fc70ab9b9370416be59e87897c3d42b20549901d2cccc3e";

const attestation = await eas.getAttestation(uid);

console.log(attestation);
```

###


# What are Attestors ?

Attestors are nodes that put data on-chain in the form of attestations or issue verifiable credentials off-chain. The nodes are modular and can perform various necessary tasks such as data signing, verification and more.


# Data Sources

Clique Attestors des use Data Sources to fetch user data as the first process of issuing attestations on chain.&#x20;

Providing a data source requires setting up an API endpoint that returns user data in JSON format. The Issuer Node can then process the JSON before issuing the attestations onchain.

### Providing a Data Source

1. Begin by establishing an API endpoint that utilizes the GET method.
2. Ensure that the endpoint includes a mandatory query parameter named "address," which is used to specify the user data to be retrieved.
3. Add an optional query parameter, "authToken," which serves as an authentication token to provide special authorized access for cases where the data should not be publicly accessible.

With these steps, you will set up a secure and functional API endpoint to serve user-specific data.

```javascript
GET METHOD
https://clique.test.api?address={userAddress}?authToken{authenticationToken
```

```json
{
  "code": 200,
  "msg": "success",
  "timestamp": "2024-01-25T12:00:00Z",
  "data": [
    {
      "fieldName": "exampleField1",
      "value": 123,
      "valueType": "integer"
    },
    {
      "fieldName": "exampleField2",
      "value": true,
      "valueType": "bool"
    },
    {
      "fieldName": "exampleField3",
      "value": "exampleString",
      "valueType": "string"
    }
    // ... additional objects can be added here
  ]
}
```


# Clique Browser Extension

Download the Clique browser extension here: <https://chromewebstore.google.com/detail/clique-browser-extension/bejghfnahjjdffjmbfooochffgcgofok>

Developers often require access to data from various online platforms for integration and functionality enhancement in their applications. Traditionally, this data access is achieved in two primary ways:

1. **APIs provided by the platforms**: This method involves using official APIs to fetch data directly from the service. However, it faces several challenges:
   * **Cost and Accessibility**: Some platforms may impose high fees or restrict access to their APIs, making it difficult or financially unviable for developers to utilize these services.
   * **Limited Scope and Permissions**: APIs may not offer complete access to all desired data or functionalities. They might require certain user permissions or account statuses, which are not always feasible or available.
2. **Direct data retrieval through user authentication in a browser**: This method involves capturing request headers, including cookies and tokens, through a browser extension to simulate a user's request and fetch data as if the user themselves were accessing it. This approach, while powerful, raises significant privacy and security concerns:
   * **Privacy Preservation**: Direct access to user data without proper safeguards can lead to privacy violations and breach of trust.
   * **Security Risks**: Handling sensitive user information without robust encryption and security measures can expose users to potential data theft and misuse.

To address these challenges and uphold user privacy and security, a sophisticated browser extension mechanism can be employed, incorporating the following principles:

1. **Encryption at Source**: The browser extension encrypts all captured request headers using a public key from a Trusted Execution Environment (TEE) immediately upon capture. This ensures that sensitive information is protected from the outset.
2. **Secure Decryption and Processing**: The encrypted data is sent directly to the TEE for decryption with a private key. This environment is secure and inaccessible to external entities, ensuring that the data processing is isolated and secure.
3. **Privacy-Preserving Data Usage**: After decryption, the necessary data is processed within the TEE to extract the required information while employing techniques like zero-knowledge proofs to obfuscate any sensitive information. This ensures that the data returned to the application is devoid of personal details, maintaining user privacy.

This approach allows developers to access and utilize data from various platforms in a manner that is both effective and respectful of user privacy and security, overcoming the limitations of traditional APIs and direct data access methods.


# FAQ


# Glossaries

Explaining Key Cryptographic Terms

1. **TEE (Trusted Execution Environments)**: Trusted Execution Environments (TEEs) are secure areas of a main processor. They guarantee code and data loaded inside are protected concerning confidentiality and integrity. A TEE provides a way to run specific code in isolation from the main operating system, enhancing security.
2. **OT (Oblivious Transfer)**: Oblivious transfer is a type of protocol in which a sender transfers one of potentially many pieces of information to a receiver, but remains unaware of what piece has been transferred. It's a fundamental protocol in the field of secure multi-party computation and private data retrieval.
3. **GC (Garbled Circuits)**: Garbled Circuits are a cryptographic protocol that allows the execution of a computation (a circuit) on encrypted inputs to produce an encrypted result. The entity evaluating the circuit does not learn anything about the inputs, outputs, or the function itself.
4. **Intel SGX (Software Guard Extensions)**: Intel SGX is a set of security-related instruction codes that are built into some modern Intel central processing units (CPUs). They allow user-level code to allocate private regions of memory, called enclaves, which are designed to be protected from processes running at higher privilege levels.
5. **AMD SEV (Secure Encrypted Virtualization)**: AMD's Secure Encrypted Virtualization (SEV) is a hardware feature aimed at securing virtual machines by encrypting the memory of each VM with a unique key, isolating it from the hypervisor or other VMs, and reducing the attack surface from privileged software.
6. **ARM TrustZone**: ARM TrustZone technology is a system-wide approach to security for a wide array of client and server computing platforms, including handsets, tablets, and other embedded devices. It creates an isolated secure world, separated from the normal world (non-secure world), where confidential and integrity-sensitive code can be executed.
7. **Set-membership Proofs**: These are cryptographic protocols that allow a prover to demonstrate that a certain piece of information belongs to a specific set of values, without revealing the actual piece of information and without the verifier needing to know all elements in the set.
8. **DCAP (Data Center Attestation Primitives)**: DCAP refers to a set of technologies used to verify the integrity and trustworthiness of hardware platforms, particularly in data centers. These primitives allow for the attestation of an enclave (secure execution environment) in a more scalable manner suitable for cloud or data center environments.
9. **Remote Attestation**: This is a process used in Trusted Computing in which a hardware device's integrity and authenticity are verified by a remote verifier. By this process, the device proves that it is running the intended software, free from malware or tampering, without revealing the data contained within the software.
10. **ORAM (Oblivious RAM)**: Oblivious RAM is a cryptographic protocol designed to obfuscate the pattern of access to a storage system. It allows a client to interact with a remote server to store and retrieve data securely, without the server learning which data is being stored or retrieved by the client.
11. **ZKP (Zero-Knowledge Proofs)**: A zero-knowledge proof is a cryptographic method that allows one party (the prover) to prove to another party (the verifier) that they know a value x, without conveying any information apart from the fact that they know the value x. It's a way of sharing proof of knowledge without revealing the knowledge itself.
12. **MPC (Multi-Party Computation)**: Multi-party computation (MPC) is a branch of cryptography that enables parties to jointly compute a function over their inputs while keeping these inputs private. MPC enables secure cross-organization data analysis and processing while maintaining data privacy.


# Socials

Website: <https://clique.tech/>\
Twitter: <https://twitter.com/clique2046>\
Substack: <https://clique2046.substack.com/><br>


