# 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](https://docs.clique.tech/build-with-clique/smart-contract-sdk "mention")
{% 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="https://1307284042-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSTne2Xo5UxvisoRfW7CR%2Fuploads%2FmvZrvlTy0UwDQygUEH6a%2Fimage.png?alt=media&#x26;token=4d1f16e1-c421-4cdb-8505-4181a99a126b" 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](https://docs.clique.tech/references/clique-query "mention")
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);
```
