# Introduction

NotVault is NotCentralised's Self-Sovereign SDK

The **NotVault** SDK is an open-source toolset designed for the swift and secure creation of self-sovereign data workflows. Its functionality spans multiple use cases, including confidential commerce and payments, token transfers, file management, and the application of verifiable credentials.

With a focus on streamlining the incorporation of Zero Knowledge Proof (ZKP) technology, NotVault emphasises best practices for encryption, decentralisation, and peer-to-peer operations in all data exchanges.

### Core Principles

**NotVault** operates on three fundamental principles:

1. **Peer-to-Peer**: To mitigate risks associated with a single point of failure.
2. **Encryption**: To maintain confidentiality at all times.
3. **Zero Knowledge Proofs**: To minimise data footprints during communication.

<figure><img src="https://848325487-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOwcZ6x9f9JNn70Upiiu4%2Fuploads%2FjmAOU40gEC8qovymSIMb%2FNotCentralised%20Venn%20Pastel.png?alt=media&amp;token=d8225b43-34b7-4065-8b5b-73e1c540493f" alt="" width="563"><figcaption></figcaption></figure>

The functionality of **NotVault** mirrors that of a wallet, facilitating the private linkage of a contact ID (such as an email) to a user's wallet. Additionally, it generates a new public/private key pair used for data encryption and signing within the ecosystem. This system negates the need to access the keys of the Ethereum wallet (typically inaccessible via API) and provides a more user-friendly method of connecting with other identities.

### Key Features

Developers leveraging **NotVault** can access a plethora of features including:

* **Wallet**: Safeguards encrypted keys and metadata.
* **Credentials**: Facilitates the generation and verification of [zkSNARK](https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof) credential proofs.
* **Vault**: Manages confidential token balances and transfers.
* **Files**: Enables self-sovereign and encrypted file storage capability through [IPFS](https://ipfs.tech/).
* **Commercial Deals**: Supports the lifecycle management of transactional or contractual agreements, including their financial settlement. It offers self-custody escrows of token payment amounts via a peer-to-peer platform.
* **Service Bus**: Provides a confidential messaging service, ensuring integrity of timestamp, source, and underlying message using a [zkSNARK](https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof).

<figure><img src="https://848325487-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOwcZ6x9f9JNn70Upiiu4%2Fuploads%2F375CVQ3kIkeSB1gJHFk1%2FColorful%20Hexagonal%20Design%20Process%20Poster.png?alt=media&amp;token=4f4e7b1a-6247-41e7-9f62-d0e65dc477c7" alt="" width="563"><figcaption></figcaption></figure>

Harness the power of **NotVault** SDK to expedite the development of secure, decentralized applications and services.

## **Open Source**

All of the code is open source under an MIT License. Enjoy

[SDK GitHub Repo](https://github.com/NotCentralised/notvault-sdk)

[EVM Smart Contracts and Circuits](https://github.com/NotCentralised/notvault-evm)


# Technical Overview

The **NotVault** SDK offers developers a robust toolkit for implementing confidential interactions by leveraging the power of  [zkSNARK](https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof) verifications and  [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) / [Public Key Encryption](https://en.wikipedia.org/wiki/Public-key_cryptography) . Integrity and consistency of these interactions are ensured through the transparency and immutability of blockchain technology.

The architecture of **NotVault** consists of a set of Solidity smart contracts that operate on an Ethereum Virtual Machine ([EVM](https://ethereum.org/en/developers/docs/evm/)) compatible Layer 1 (L1) network, alongside a JavaScript npm package. These components enable:

1. **Obfuscation of fungible token balances:** This is achieved via the  [Poseidon](https://www.poseidon-hash.info) hash function. Note that only the token balances and the value of transfers are kept confidential. The identity, source, and destination of the transfers relating to these tokens remain public.
2. **Confidential storage and indexing of files onto IPFS:** Each file is encrypted with a unique secret key using the [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) algorithm, providing a secure method for file storage and retrieval.
3. **Verification of data integrity:** Credential workflows employing [zkSNARK](https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof) allow for secure and efficient verification of data integrity.

The **NotVault** SDK's codebase is structured into three primary sections:

* [**Typescript**](https://www.typescriptlang.org) [**NPM**](https://www.npmjs.com) **package:** This is where encryption, proof generation, and connectivity to both blockchains and [IPFS](https://ipfs.tech) are handled.
* [**Solidity**](https://soliditylang.org) **smart contracts:** These define the vault, balances, and transactional logic, providing the framework for secure and confidential transactions.
* [**Circom**](https://docs.circom.io) **circuits:** These define the zero knowledge proof logic, facilitating the secure verification of data without revealing any unnecessary information.

Developers can leverage the **NotVault** SDK to accelerate the development of secure, confidential, and integrity-focused applications.


# Workflows

**NotVault** SDK is a powerful toolset that enables self-sovereign handling of various workflows pivotal to modern decentralized applications. It facilitates secure and confidential operations, catering to diverse functionalities such as file storage, token transfers, contractual/commercial agreements, credential verification, and confidential data management.

In the following sections, we'll delve into each of these workflows individually, providing you with a comprehensive understanding of their functioning and the potential they offer. Here is an overview of the workflows that will be discussed:

1. **File Storage:** Confidential and secure storage of files.
2. **Token Transfers:** Secure handling and transfer of fungible tokens.
3. **Contractual/Commercial Agreements:** Facilitating confidential and secure contractual or commercial agreements.
4. **Credential Verification:** Efficient and confidential verification of credentials.
5. **Confidential Event Messaging:** Secure handling and management of confidential event messages.

Understanding these workflows will provide a solid foundation for leveraging the capabilities of the **NotVault** SDK in your development projects. Let's dive deeper into each workflow.


# Files

The storage of and access to files through censorship-resistant and confidential technologies is essential to many applications.

#### Core Features:

This SDK harnesses cutting-edge technologies to deliver:

* **Censorship Resistance:** Utilizing the InterPlanetary File System ([IPFS](https://ipfs.tech)), a peer-to-peer file storage protocol, **NotVault** ensures your file's data is resistance to censorship.
* **Confidentiality:** By implementing a Single Key Encryption methodology rooted in the Advanced Encryption Standard ([AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard)) algorithm, **NotVault** guarantees the confidentiality of your files. This method creates a unique secret for each file, which is then used to encrypt the file, enabling efficient and confidential file distribution.
* **Private File List:** **NotVault** empowers each user with a private list of their files uploaded to IPFS. This list serves as a reference and includes:
  * File Name
  * Upload Date
  * Secret Encryption Key

#### Workflow

Using **NotVault**, you can create workflows with the following steps:

* **Upload:** When a file is selected for upload, the following process is initiated:
  1. **NotVault** generates a UUID-based random key.
  2. This key is used to encrypt the file via the [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) algorithm.
  3. The encrypted file is then sent to [IPFS](https://ipfs.tech).
  4. Keep in mind, the file departs from the **NotVault** runtime only after encryption.
* **Listing:** Users can access their private file list, returning a list of names, upload dates, and secret encryption keys.
* **Retrieval:** Users can fetch a file from [IPFS](https://ipfs.tech) and decrypt it within the **NotVault** runtime using the corresponding secret key. This design ensures the reduction of potential content leaks.
* **Deletion:** Users can remove a file from their private list and unpin it from [IPFS](https://ipfs.tech).

> Important: Full confidentiality can only be attained by refraining from sharing the data itself, but rather by sharing cryptographic derivates of the confidential data. When a dataset is accessible to more than one person, managing the data's footprint becomes a challenge.


# Credentials

**NotVault** enables developers to create robust and secure data integrity verification systems. This feature is critical in developing functional, real-world workflows in trustless environments.

#### Objects in the Workflow

Three primary objects are involved in this workflow:

* **Dataset**: This is a collection of data, the utility of which depends on the integrity of its contents.
* **Credential**: This is an object derived from the Dataset that contains additional information about the Dataset's validity and integrity.
* **Query**: This is a set of questions concerning the validity and integrity of a Credential.

#### Roles in the Workflow

There are three roles in this workflow:

* **Person**: This can be an individual or entity that relates to or is the subject of a certain Dataset.
* **Issuer**: An individual or entity that attests to the validity of a Person's Dataset. The Issuer creates a Credential, which is an atomic Dataset that has been verified, encrypted, and signed.
* **Verifier**: An individual or entity that wishes to verify that a Query relating to a Credential is true.

#### Workflow Steps

Here is the step-by-step process of this workflow:

1. **Dataset Creation**: A Person creates a Dataset that is dependant on the integrity of its contents. An example of such a Dataset is a Passport, where its utility is tied to its recognized integrity.
2. **Credential Creation**: An Issuer verifies the integrity of the Person's Dataset and generates a Credential. This new object contains an encrypted version of the Dataset that is signed by the Issuer. For instance, in the Passport example, the Issuer would be the specific government responsible for issuing the passport.
3. **Query Creation**: A Verifier who wishes to check if the Dataset matches specific criteria or features creates a Query outlining these constraints. The Verifier then shares the Query with the Person who owns the Credential. In the Passport example, the Verifier might be a border control officer who checks the validity of the passport.
4. **Proof Generation**: The Person generates a proof showing that their Credential meets the constraints or criteria specified in the Query. This proof is then sent to the Verifier.
5. **Proof Verification**: The Verifier validates the proof. It's important to note that the underlying Credential or data is never shared throughout this workflow—only the Query criteria and the proof corresponding to the Query.

This functionality of **NotVault** offers a robust method to verify data integrity without exposing the actual data, thereby maintaining the privacy and security of the information. Developers can use this functionality to build a wide range of applications, from identity verification to secure data access controls.


# Tokens

**NotVault** ensures the confidential management and transaction of tokens, utilizing both censorship-resistant technologies and smart contracts known as 'The Vault'.

#### Key Features

Here are some core features provided by the Token SDK:

* **Token Life-cycle Management**: **NotVault** allows you to manage the entire life-cycle of token transactions with ease and high-level security.
* **The Vault Smart Contract**: The Vault stores hash values of token balances instead of conventional numerical values. This further promotes secure and private token transactions.
* **Zero Knowledge Proofs**: zkSNARKs or Zero Knowledge Proofs ensure that balance updates remain confidential yet consistent, bolstering the privacy of transactions.
* **Asynchronous Transfer Pattern**: **NotVault** adopts an asynchronous transfer pattern for private transfers. Unlike synchronous ERC20 transfers, these transfers require the receiver's acceptance before completion.

### Roles in the Token Workflow

In a **NotVault** token transaction workflow, two roles are crucial:

* **Sender**
* **Receiver**

#### Workflow Steps

Below is a step-by-step walkthrough of a token transaction using **NotVault**:

1. **Deposit**: The sender deposits tokens from their public balance.
2. **zkSNARK Proof Generation by Sender**: Before a sender can transfer tokens, they generate a zk proof. This verifies that the sender knows their balance before the transfer and ensures the transferred amount is less than or equal to the available balance, avoiding double spending.
3. **Send Request**: The transferred amount is locked in The Vault smart contract as a Send Request, identified by a unique ID.
4. **Balance Update by Receiver**: When ready to accept the transfer, the receiver identifies the Send Request through its unique ID and updates their balance in The Vault.
5. **zkSNARK Proof Generation by Receiver**: To update their balance, the receiver generates a zk proof, verifying that they know the transferred amount and their balance before the update.
6. **Withdrawal**: Finally, the receiver withdraws the accepted amount from their private balance to their public standard balance.

#### A Use Case Scenario

To put things into perspective, here's an example scenario of token workflows in **NotVault**:

* Owner A (sender) has 1000 tokens in their public balance. They deposit 100 of these tokens into their private balance within The Vault.
* Owner A's private balance is now 100 tokens, represented on-chain as a hash.
* Owner A calculates their new balance after sending 10 tokens, and creates a new hash for the remaining 90 tokens.
* Using zkSNARK, Owner A verifies the balance update's consistency and updates their on-chain balance in The Vault, replacing the old hash with the new one.
* Owner A initiates a Send Request, locking the 10 tokens in it.
* Owner B (receiver), upon identifying the Send Request through its unique ID, calculates their new balance after adding the transferred tokens, and creates a new balance hash.
* Owner B creates a zkSNARK proof to verify their new balance hash is indeed the old balance plus the transferred amount.
* Owner B updates their on-chain balance in The Vault using the proof.
* Finally, the smart contract invalidates the Send Request's key to ensure it's spent only once.


# Deals

**NotVault** offers the ability to digitise term sheets and payment schedules for commercial or contractual relationships through smart contracts, streamlining commercial relationships and augmenting security and efficiency.

These relationships can exist between any parties - natural persons or legal entities such as corporations.

#### What is a Deal?

A 'Deal' in **NotVault** is a digital representation of a term sheet consisting of deliverables and payment schedules. Payments are governed by programmed rules which act as prerequisites for the release of payments. Upon the start of the agreement, collateral is locked into 'The Vault' and utilized to satisfy the payments when their conditions are triggered.

> **Note**: Both term sheets and payment amounts maintain confidentiality. Term sheets are encrypted and only visible to the participants of the trade or commercial agreement. Payment amounts are confidential, achieved using the same methods as detailed in the Token Workflows.

#### Roles in the Workflow

There are two primary roles in this workflow:

* **Payor**
* **Payee**

### Workflow Steps

Here is the step-by-step process to leverage **NotVault**'s smart contract term sheet and payment functionalities:

1. **Term Negotiation**: The payee and the payor negotiate and agree on the terms of a deal.
2. **Term Sheet Creation**: The payee generates a digital term sheet and payment schedule, which includes the initial collateral.
3. **Payment Conditions Definition**: During the creation and minting of the term sheet, the payee states the programmed payment conditions.
4. **Term Sheet Agreement**: The payor agrees to the digital term sheet and payment terms.
5. **Collateral Lock-In**: The payor locks in the initial collateral as per the payment terms, shifting tokens into the digital escrow account.
6. **Payment Release**: As the payment conditions are met, the collateralised amounts are unlocked and made available to the payee for withdrawal.

#### Payment Conditions

The payment release conditions include:

* The payee can withdraw after a certain date.
* The payor can cancel payments that have not been withdrawn after a certain date.
* The payee can withdraw when an approved oracle feed reaches a certain value.


# Service Bus

This documentation outlines the workflows associated with the creation of confidential and integrity-focused event messages, all made possible through the **NotVault** Service Bus.

The **NotVault** Service Bus enables developers to establish event messages with guaranteed integrity in relation to:

1. **Event Source:** Ensuring the event's origin can be accurately traced.
2. **Event Timestamp:** Capturing the exact time the event message was created.
3. **Zero-knowledge Proof:** Allowing the event's source to prove they possess the information required to generate the event without revealing the underlying information.

### Workflow Steps

Creating an event message involves the following two critical steps:

1. **Event Message Generation:** Here, the source creates an event message, incorporating three key components:
   * *Key:* This serves as a unique identifier for the event.
   * *Hashed Value:* A secure hash derived from the original value, preserving its confidentiality.
   * *Proof:* A Zero-Knowledge Proof is created, verifying that the source knows the original value of the hash, but without disclosing it.
2. **Event Message Verification and Acceptance:** After the event message is generated, the Service Bus smart contract then verifies the Zero-Knowledge Proof. If the proof passes the verification process, the event message is accepted.

By following these steps and using the **NotVault** SDK effectively, developers can establish workflows for confidential and integrity-focused event messages.


# SDK

Engaging with **NotVault** can be done through a Typescript SDK downloadable as an [NPM](https://www.npmjs.com/package/@notcentralised/notvault-sdk) package.

```sh
    npm i @notcentralised/notvault-sdk
```

Continue to the next sections to understand each workflows implementation in more detail.


# Initialise

In order to begin using **NotVault** within your TypeScript projects, you will need to initialise the library correctly. This initialisation process sets up the necessary connections and providers for the library's operations, particularly for interacting with IPFS and the Ethereum blockchain via JSON-RPC.

#### Environment Variables

Prior to initializing **NotVault**, you'll need to ensure the following environment variables are set:

1. `PUBLIC_URL`
2. `PINATA_API_KEY`
3. `PINATA_SECRET_API_KEY`

These are critical for the functioning of IPFS file operations and the connectivity with Pinata.

#### Initialization Steps

To initialise **NotVault** in a TypeScript environment, follow the steps below:

1. **Import the necessary libraries**:

   ```typescript
   import { NotVault } from '@notcentralised/notvault-sdk';
   import { ethers } from 'ethers';
   ```
2. **Instantiate the NotVault class**:

   ```typescript
   const vault = new NotVault();
   ```
3. **Create an JSON RPC connection**:

   * Set up a new instance of `JsonRpcProvider` from the `ethers` library. You need to pass in your RPC Host URL to the `JsonRpcProvider` constructor.
   * Create a `signer` by creating a new instance of the `Wallet` class from the `ethers` library. Pass in your private key and the custom HttpProvider instance.

   ```typescript
   const customHttpProvider = new ethers.providers.JsonRpcProvider('... RPC Host ...');
   const signer = new ethers.Wallet('... Private Key ...', customHttpProvider);
   ```
4. **Initialise the vault object**: Now, using the `.init` function of the `vault` instance, pass in your Chain ID and the `signer` instance created in the previous step.

   ```typescript
   vault.init('... Chain ID ...', signer);
   ```

After successfully following these steps, your **NotVault** instance is set up and ready for file operations on IPFS and transactions on an EVM compatible blockchain.


# Register and Generate Keys

Once you've initialised your **NotVault** library as detailed in the previous section, you're now ready to register an account and perform key generation.

To register an account and generate keys in a TypeScript environment, follow the steps below:

1. **Import the necessary libraries**:

   ```typescript
   import { NotVault } from '@notcentralised/notvault-sdk';
   ```
2. **Instantiate the NotVault class**:

   ```typescript
   const vault = new NotVault();
   ```
3. **Register the contact ID and keys**:

   * Use the `.register` method of the `vault` instance to register the account. This method takes in several parameters and callback functions to facilitate the registration process.
   * The parameters for this method include the wallet address, email or 0xWallet, and the secret key.
   * The callback functions include retrieving the public key from the crypto wallet, decrypting with the crypto wallet, and a success callback that logs the public key and contact ID.

   ```typescript
   await vault.register(
       '... Wallet Address ...', 
       '... Email or 0xWallet ...',
       '... Secret Key ...',
       async () => { return '... Public Key ...'; }, // Retrieve public key from crypto wallet    
       async (encryptedPrivateKey: string) => { return '... Private Key ...'; }, // Decrypt with crypt wallet
       async (publicKey: string, contactId: string) => { console.log('Success!', publicKey, contactId); } // Success
   );
   ```

With these steps, your account is registered in **NotVault** and your keys are properly set up for further operations. This registration process is an essential step for successfully using **NotVault** to perform secure and confidential operations on your data and tokens.


# Files

The Files SDK offers developers the functionality of an encrypted IPFS drive. It creates a list of references and secret keys to files stored on IPFS, where each file is encrypted with its own secret. This way, if one secret key is compromised, there is no compromise of the entire drive.

> Note: The list of files and secrets is only visible to the Wallet.

Here is a step-by-step guide on how to work with files in NotVault using TypeScript:

1. **Import the necessary libraries**:

   ```typescript
   import { NotVault, Files, FileEntry } from '@notcentralised/notvault-sdk';
   ```
2. **Instantiate the NotVault and Files classes**:

   ```typescript
   const vault = new NotVault();
   const files = new Files(vault);
   ```
3. **Add a new file**:

   * Use the `add` method of the `files` instance to add a file to the vault.
   * The method requires the filename and the content of the file. The content should be in Base64 format when dealing with binary data.
   * The method also accepts a callback function that reports the progress of the upload operation.

   ```typescript
   const newFilesList : FileEntry[] = await files.add(
       '... File Name ...', 
       '... Super secret text, usually in Base64 format when dealing with binary data ...', 
       (event: any) => {
           const percent = Math.floor((event.loaded / event.total) * 100);
           console.log(`Progress ${percent}%`);
       }
   );
   ```
4. **Retrieve the contents of a file given its CID**:

   * Use the `get` method of the `files` instance to retrieve a file from the vault using its Content Identifier (CID).

   ```typescript
   const retrievedFile : FileEntry = await files.get(`... File CID in IPFS ...`);
   ```
5. **List all the files linked to a specific wallet**:

   * Use the `list` method of the `files` instance to retrieve a list of all files linked to the specific wallet in the vault.

   ```typescript
   const allFiles : FileEntry[] = await files.list();
   ```
6. **Remove a file from a private list**:

   * Use the `remove` method of the `files` instance to remove a file from the vault using its Content Identifier (CID).

   ```typescript
   const newFilesAfterRemoval : FileEntry[] = await files.remove(`... File CID in IPFS ...`);
   ```

By following these steps, you can manage your files within the NotVault environment securely and efficiently.


# Credentials

The Credentials SDK offers developers a way to manage the life-cycle of credentials including creation, proving and verification. The SDK also enables the storage of credentials using the Files SDK. The list of credentials is ONLY visible to the Wallet owner and is used for storage purposes only.

*Note: The length of each entry in the Credential is constrained by a maximum of 32 characters*

1. **Import the necessary libraries:**

```typescript
import { NotVault, Files, Credentials } from '@notcentralised/notvault-sdk';
```

2. **Instantiating the NotVault classes:**

```typescript
const vault = new NotVault();
const files = new Files(vault);
const credentials = new Credentials(vault, files);
```

With these statements, we instantiate the `NotVault`, `Files`, and `Credentials` classes, providing the necessary foundations for credential operations.

3. **Defining a dataset:**

Here, we define a dataset that will be verified to create a credential. The example below describes a passport dataset.

```typescript
const passport_dataset : any = {
    id: 100,
    first_name: 'Pablo',
    last_name: 'Erchanfrit',
    dob: Math.floor(new Date('1990-08-10').getTime() / 1000), // unix format
    country: 'Liechtenstein'
};
```

4. **Defining a schema for the credential:**

We create a schema defining the structure of the credential.

```typescript
const schema : Schema = {
    id: 'passport',
    type: 'alphaNumericalData',
    fields: [
        {
            id: 'id',
            name: 'Passport Number',
            type: 'number'
        },
        {
            id: 'first_name',
            name: 'First Name',
            type: 'string'
        },
        {
            id: 'last_name',
            name: 'Last Name',
            type: 'string'
        },
        {
            id: 'dob',
            name: 'Date of Birth',
            type: 'date'
        },
        {
            id: 'country',
            name: 'Country',
            type: 'string'
        }
    ]
};
```

5. **Issuing a credential:**

Issuing a Credential is the process of creating a cryptographic dataset which is derived from an initial dataset. The Credential is an attestation of the integrity of the original dataset.

```typescript
const passport_credential = await credentials.issue(
    passport_dataset, 
    schema, 
    '... Owner Public Key ...', 
    '... Signature of source credential ...',
    true // If you wish to add this credential to the wallets list of credentials using the Files SDK.
);
```

6. **Creating a query:**

A query with constraints or criteria is necessary to generate a proof. We are proving that a Credential respects certain constraints. In the example below, we are proving that the date of birth in Credential above is between specified values. Furthermore, we are sharing an aggregated hash of the Last Name and Country fields, as this example relates to a passport.

Upper and lower boundary constraints are only applied to numbers and dates. Text data can only be verified by exact matches. Read more on this in the verification section below.

The proof will not be generated if the numerical data is not within the ranges stated in the constraints.

```typescript
const query: { constraints:any, fields:any[] } = {
    constraints:{ // Upper and lower boundary constraints are only applied to numbers and dates
        dob: { lower: Math.floor(new Date('1980-08-10').getTime() / 1000), upper: Math.floor(new Date('1999-08-10').getTime() / 1000)},
    },
    fields:['last_name', 'country'] // Text data can only be verified by exact matches
};
```

7. **Generating a proof:**

A query with constraints or criteria is necessary to generate a proof. We are proving that a Credential respects certain constraints. In the example below, we are proving that the date of birth in Credential above is between specified values. Furthermore, we are sharing an aggregated hash of the Last Name and Country fields, as this example relates to a passport.

Upper and lower boundary constraints are only applied to numbers and dates. Text data can only be verified by exact matches. Read more on this in the verification section below.

The proof will not be generated if the numerical data is not within the ranges stated in the constraints.

```typescript
const proof : Proof = await credentials.prove(query, passport_dataset, schema);
```

8. **Verifying a credential:**

Verifying a proof requires the values of the **fields** above. As mentioned, proofs are only generated if the numerical constraints are met. The proof will contain an aggregated hash of the text data.

The verification happens when the verifier creates an aggregated hash of the text values, which they expect the credential to contain. The first parameter below contains this information and the verification function will only return **true** if this information matches the information implicitly contained in the proof.

```typescript
const isValid : boolean = await credentials.verify({
        last_name: 'Erchanfrit',
        country: 'Liechtenstein'
    }, 
    '... Public key of the issuer ...', 
    proof.schema, 
    proof.proof
);
```

9. **Listing all credentials:**

We fetch all credentials.

```typescript
const allCredentialsList = await credentials.list();
```

10. **Adding a new credential:**

We add a new credential to the list.

```typescript
const newCredentialsListAfterAdding : FileEntry[] = await credentials.add(
    `... any description of the dataset ...`,
    JSON.stringify(passport_dataset)
);
```

11. **Removing a credential:**

We eliminate a credential from the private list.

```typescript
const newCredentialsListAfterRemoving : FileEntry[] = await credentials.remove(`... File CID in IPFS ...`);
```

Please refer to the original TypeScript code context for a detailed breakdown of the parameters required for each function.


# Tokens

The operations covered here include depositing an amount into the vault's private balance, sending a confidential amount, retrieving a confidential amount, and withdrawing an amount from the vault.

First, ensure you've imported the required libraries:

```typescript
import { NotVault, Tokens } from '@notcentralised/notvault-sdk';
```

### Instructions

1. **Instantiating the NotVault and Tokens classes:**

```typescript
const vault = new NotVault();
const tokens = new Tokens(vault);
```

This initializes the `NotVault` and `Tokens` classes, providing the groundwork for token operations.

2. **Depositing an amount into the vault's private balance:**

```typescript
await tokens.deposit('...Token Address...', BigInt(1000) /* token amount */ * BigInt(10 ** 18) /* token decimal places */);
```

This command deposits a specific amount into the vault's private balance. The amount is calculated as a product of the token amount and the token decimal places.

3. **Sending a confidential amount:**

```typescript
const idHash = await tokens.send(
    '...Token Address...',
    '... Email or Receipient address ...',
    BigInt(1000) /* token amount */ * BigInt(10 ** 18) /* token decimal places */
);
```

With this command, you can send a confidential amount to a recipient. The transaction id hash is stored for future reference.

4. **Retrieving a confidential amount:**

```typescript
await tokens.retreive(
    idHash,
    '...Token Address...',
    BigInt(1000) /* token amount */ * BigInt(10 ** 18) /* token decimal places */
);
```

This command allows for the retrieval of a confidential amount using the transaction id hash. This can be used in the event of a need for a transaction review or audit.

5. **Withdrawing an amount:**

```typescript
await tokens.withdraw(
    '...Token Address...',
    BigInt(1000) /* token amount */ * BigInt(10 ** 18) /* token decimal places */
);
```

This function permits you to withdraw a specified amount from the vault. This is useful for managing the flow of tokens and controlling the vault's balance.

Please refer to the original TypeScript code context for more granular detail on the parameters required for each function.

***

### Reading Token Balances

This section explains the steps to read various balances for a specific address using the NotVault SDK. This includes checking the private (confidential), public, locked outgoing, and locked incoming balances.

1. **Check the various balances a given address has in the vault:**

```typescript
const balance : Balance = await tokens.getBalance('...Token Address...');
```

This step fetches the `Balance` object for the given token address, which includes all different types of balances associated with the address.

2. **View the private or confidential balance:**

```typescript
console.log('Private or Confidential Balance', balance.privateBalance);
```

This logs the confidential balance, providing a view of the amount kept private in the vault.

3. **View the public balance:**

```typescript
console.log('Public Balance', balance.balance);
```

This logs the public balance associated with the token address, which indicates the publicly viewable amount.

4. **View the locked outgoing balances:**

```typescript
balance.lockedOut.forEach(element => {
    console.log('Locked Out', element);
});
```

This iterates over and logs each locked outgoing balance, providing visibility into amounts that are locked for outgoing transactions.

5. **View the locked incoming balances:**

```typescript
balance.lockedIn.forEach(element => {
    console.log('Locked In', element);
});
```

This iterates over and logs each locked incoming balance, which can provide insights into amounts locked for incoming transactions.


# Deals

The Deals SDK offers developers a way to digitise commercial agreement term sheets and payment terms through smart contracts.

### Create Deal

A deal is the representation of a term sheet with certain deliverables and associated payment schedules. Payments can have programmed rules attached for their release. Payments are initially locked into the vault upon the commencement of the agreement, prior to meeting the specific rules / tests allowing their release. Users can specify the value of the initial payments locked into the escrow function of the vault. This could be partial or complete collateralisation of the payments potentially due under the term sheet agreement.

The deal is created by the party expecting to be to be paid. Creation of the deal implied an acceptance to the terms by the payee, because otherwise, why would one create a deal with those terms?

### Instructions

First, ensure you've imported the required libraries:

```typescript
import { NotVault, Tokens, Deals, Files } from '@notcentralised/notvault-sdk';
```

1. **Instantiate the NotVault, Tokens, Files, and Deals classes:**

```typescript
const vault = new NotVault();
const tokens = new Tokens(vault);
const files = new Files(vault);
const deals = new Deals(vault, tokens, files);
```

This initialization is crucial for managing deals, tokens, and files within the NotVault.

3. **Create a deal**

These initialisations provide the necessary setup to manage deals, tokens, and files within the NotVault.

```typescript
const deal = await deals.createDeal(
    '... Token Address ...', 
    '... Oracle Address ...',
    { 
        name: '... Deal Name ...', 
        counterpart: '... Email or Address ...',
        description: '... Deal Description ...', 
        notional: 10000,
        initial: 1000,
        unlock_sender: Math.floor(new Date('2023-08-10').getTime() / 1000), // unix format
        unlock_receiver: Math.floor(new Date('2024-08-10').getTime() / 1000), // unix format
        oracle_owner: '... Owner Address ...',
        oracle_key: 1,
        oracle_value: 1
    },
    {
        data: [{
            created: 1685512747,
            data: 'B64',
            name: 'filename'
        }]
    });
```

The `create` method of the `Deals` class is used to create a deal. It returns a deal\_cid (content identifier) for the newly created deal. Provide the required parameters:

* `Token Address`: The address of the token to be used in the deal.
* `Oracle Address`: The address of the oracle.
* An object containing deal details:
  * `Deal Name`: The name of the deal.
  * `Email or Address`: The address of the recipient of the deal.
  * `Deal Description`: A description of the deal.
  * `notional`: The total amount of tokens involved in the deal.
  * `initial`: The initial amount to start the deal.
  * `unlock_sender`: The date when the sender can withdraw from the deal, represented in UNIX format.
  * `unlock_receiver`: The date when the receiver can withdraw from the deal, represented in UNIX format.
  * `Owner Address`: The address of the deal's owner.
  * `oracle_key`: The key provided by the oracle.
  * `oracle_value`: The value provided by the oracle.
* An object representing deal's associated data:
  * `created`: The creation timestamp.
  * `data`: The base64 encoded data of the file.
  * `name`: The name of the file.

2. **Accept Deal**

Once a deal has been created, the payor accepts the terms and payment schedule and creates a payment linked to the agreed upon initial collateral amount stated in the deal term sheet.

```typescript
const hash_id = await deals.accept(
    '... Token Address ...',
    '... Email or Address ...',
    BigInt(1000) /* token amount */ * BigInt(10 ** 18) /* token decimal places */,
    1, // deal ID
    '... Oracle Address ...',
    '... Owner Address ...',
    1, // Oracle Value
    1, // Oracle Key
    Math.floor(new Date('2023-08-10').getTime() / 1000), // date when payer can withdraw in unix format
    Math.floor(new Date('2024-08-10').getTime() / 1000), // date when payee can withdraw in unix format
);
```

The `accept` method of the `Deals` class is used to accept a deal, and it returns a hash ID for the accepted deal. You need to provide the required parameters:

* `Token Address`: The address of the token being used in the deal.
* `Email or Address`: The address of the recipient of the deal.
* `token amount`: The amount of the token in the deal. The provided value is multiplied by 10^18 to account for the token's decimal places.
* `deal ID`: A unique identifier for the deal.
* `Oracle Address`: The address of the oracle.
* `Owner Address`: The address of the owner.
* `Oracle Value`: The value provided by the oracle.
* `Oracle Key`: The key provided by the oracle.
* `date when payer can withdraw`: The date when the payer can withdraw from the deal, represented in UNIX format.
* `date when payee can withdraw`: The date when the payee can withdraw from the deal, also represented in UNIX format.


# Service Bus

The guide walks you through the process from importing necessary libraries to adding and retrieving event values.

Firstly, import the required libraries:

```typescript
import { NotVault, ServiceBus } from '@notcentralised/notvault-sdk';
```

### Instructions

1. **Instantiate the NotVault and ServiceBus classes:**

```typescript
const vault = new NotVault();
const servicebus = new ServiceBus(vault);
```

The `NotVault` instance is required to initialize the `ServiceBus` class, which manages events in the confidential service bus.

2. **Define the Key and Confidential Value:**

```typescript
const key = BigInt(1);
const confidentialValue = BigInt(2);
```

The `key` and `confidentialValue` are BigInt values. You may replace `1` and `2` with any integers of your choice.

3. **Add an event value:**

```typescript
await servicebus.setValue(key, confidentialValue);
```

You can add an event value to the confidential service bus by calling the `setValue()` method. It requires two parameters: the key and the confidential value.

4. **Get an event value:**

```typescript
const retrievedConfidentialValue : BigInt = await servicebus.getValue("... Wallet Address ...", key);
```

You can retrieve the event value from the confidential service bus using the `getValue()` method. It requires two parameters: the wallet address and the key. It will return the confidential value associated with the given key.


# Contracts

⚠️ WARNING ⚠️

The EVM Compatible smart contracts underpinning the infrastructure offer the transactional and integrity layer of the functionality.

> Note: These contracts are under development, use at your own risk.

<table data-full-width="true"><thead><tr><th></th><th width="122">GOERLI</th><th width="119">SEPOLIA</th><th width="163">Hedera Testnet</th><th width="148">Base Goerli</th><th>Gas*</th></tr></thead><tbody><tr><td>Wallet</td><td><a href="https://goerli.etherscan.io/address/0x5F4f89bd3B61740F2E8264FE9ff8e2Cdf295B2bF">0x5F4...</a></td><td><a href="https://sepolia.etherscan.io/address/0x4b8Dfd5BdE2907c9b45E5C392421DE5B31E88313">0x4b8...</a></td><td><a href="https://hashscan.io/testnet/contract/0.0.14163364">0x756...</a></td><td><a href="https://goerli.basescan.org/address/0xF972E1A76F08c377bF0DB8ed52a231EE99bD0b41">0xF97...</a></td><td>1,162,239</td></tr><tr><td>Vault</td><td><a href="https://goerli.etherscan.io/address/0x4C1fcce4474CEA690Af57f08eE189CaC4f2e4721">0x4C1...</a></td><td><a href="https://sepolia.etherscan.io/address/0x38Ad327aDF4c763C0686ED8DBc6fa45c7dAb29AE">0x38A...</a></td><td><a href="https://hashscan.io/testnet/contract/0.0.14163367">0xd80...</a></td><td><a href="https://goerli.basescan.org/address/0x9d68228C8E043630041Cf08f911D2EC329390555">0x9d6...</a></td><td>5,041,627</td></tr><tr><td>Deal</td><td><a href="https://goerli.etherscan.io/address/0xe8Fb759ABA61091700eBF85F35b866c751Ba6DD6">0xe8F...</a></td><td><a href="https://sepolia.etherscan.io/address/0x52329a088c7d8EBd368fe67a6d3966E3BB42A5BB">0x523...</a></td><td><a href="https://hashscan.io/testnet/contract/0.0.14163369">0x38c...</a></td><td><a href="https://goerli.basescan.org/address/0xFCC3B351310c2E16035E2126cee14175F5350c91">0xFCC...</a></td><td>4,328,511</td></tr><tr><td>Oracle</td><td><a href="https://goerli.etherscan.io/address/0xa946D99b5dDdd21688AfBBF16c196052c93577Ba">0xa94...</a></td><td><a href="https://sepolia.etherscan.io/address/0x8b2a145b8ccdAfC79DDD3D6bE56Bd513a1e0AA49">0x8b2...</a></td><td><a href="https://hashscan.io/testnet/contract/0.0.14163370">0xeEB...</a></td><td><a href="https://goerli.basescan.org/address/0xbbf1D9AE5919E25567e17FE0e5187f35F6F562a6">0xbbf...</a></td><td>693,393</td></tr><tr><td>ServiceBus</td><td><a href="https://goerli.etherscan.io/address/0x9894CE6BB4dFdE24ACD6276D9CF4Fbd20d67d272">0x989...</a></td><td><a href="https://sepolia.etherscan.io/address/0x5A95e579944a53370c51760A2db3dF6b96b866F1">0x5A9...</a></td><td><a href="https://hashscan.io/testnet/contract/0.0.14195226">0xCe0...</a></td><td><a href="https://goerli.basescan.org/address/0x24A4d3335f88e59FA672093226D666B1D9CAACAf">0x24A...</a></td><td>735,119</td></tr></tbody></table>

*\*Deployment Gas fees*

#### Method Costs

These are the costs measured on the Goerli and Sepolia testnets. The gas limits are hardcoded for Hedera since the network doesn't have a gas estimation function currently.

|        | Methods            | Approx Gas | Gas Limit |
| ------ | ------------------ | ---------- | --------- |
| Wallet | registerKeys       | 684,397    | 700,000   |
| Wallet | setValue           | 137,643    | 200,000   |
| Wallet | setFileIndex       | 90,313     | 100,000   |
| Wallet | setCredentialIndex | 90,313     | 100,000   |
| Vault  | deposit            | 552,191    | 600,000   |
| Vault  | withdraw           | 374,927    | 400,000   |
| Vault  | createRequest      | 1,152,414  | 1,200,000 |
| Vault  | acceptRequest      | 618,821    | 650,000   |


# Wallet

## ConfidentialWallet Contract

The `ConfidentialWallet` contract is a key part of the NotVault SDK which is responsible for confidential management of keys, files, credentials, and value storage. Let's dive into each function present in this contract:

### Key Management Functions

* **registerKeys**: This function associates the sender's Ethereum address with their public key, encrypted private key, encrypted secret, contact ID, and an encrypted contact ID.

  ```solidity
  function registerKeys(
      string memory publicKey, 
      string memory encryptedPrivateKey, 
      string memory encryptedSecret, 
      string memory contactId, 
      string memory encContactId
  );
  ```
* **getPublicKey**: This function returns the public key associated with a given Ethereum address.

  ```solidity
  function getPublicKey(
      address account
  ) public view returns (string memory);
  ```

### File Index Management Functions

* **getFileIndex**: Returns the file index associated with a given Ethereum address.

  ```solidity
  function getFileIndex(
      address account
  ) public view returns (string memory);
  ```
* **setFileIndex**: This function allows the sender to set the file index associated with their Ethereum address.

  ```solidity
  function setFileIndex(
      string memory value
  ) public;
  ```

### Credential Management Functions

* **getCredentialIndex**: Returns the credential index associated with a given Ethereum address.

  ```solidity
  function getCredentialIndex(
      address account
  ) public view returns (string memory);
  ```
* **setCredentialIndex**: This function allows the sender to set the credential index associated with their Ethereum address.

  ```solidity
  function setCredentialIndex(
      string memory value
  ) public;
  ```
* **getCredentialStatus**: Returns the status of a specific credential for a given Ethereum address.

  ```solidity
  function getCredentialStatus(
      address account, 
      string memory id
  ) public view returns (bool);
  ```
* **setCredentialStatus**: This function allows the sender to set the status of a specific credential associated with their Ethereum address.

  ```solidity
  function setCredentialStatus(
      string memory id, 
      bool status
  ) public;
  ```

### Value Store Management Functions

* **getValue**: Returns the value associated with a specific key for a given Ethereum address.

  ```solidity
  function getValue(
      address account, 
      string memory key
  ) public view returns (string memory);
  ```
* **setValue**: This function allows the sender to set a value for a specific key associated with their Ethereum address.

  ```solidity
  function setValue(
      string memory key, 
      string memory value
  ) public;
  ```


# Vault

## ConfidentialVault Contract

The `ConfidentialVault` contract is a crucial component of the NotVault SDK. This contract is responsible for private token management. It maintains private balances and executes private transactions using zkSNARKs proofs. It is specifically designed to interact with ERC20 tokens.

### Structure Definitions

* **CreateRequestMessage**: This structure is used for creating a request for a confidential transfer. It contains recipient, denomination, and other related details of a private transfer.
* **SendRequest**: This structure keeps the record of the confidential transfer requests. It contains details like the sender, recipient, and the amount of the transfer.

### Public Functions

* **privateBalanceOf**: This function returns the private balance of a given account in a specified denomination.

  ```solidity
  function privateBalanceOf(
      address account,
      address denomination
  ) public view returns (string memory);
  ```
* **getSendRequestBySender**: This function returns all the `SendRequest` made by a given account.

  ```solidity
  function getSendRequestBySender(
          address account
  ) public view returns (SendRequest[] memory);
  ```
* **getSendRequestByReceiver**: This function returns all the `SendRequest` which have a given account as the receiver.

  ```solidity
  function getSendRequestByReceiver(
      address account
  ) public view returns (SendRequest[] memory);
  ```
* **getSendRequest**: This function returns the details of a `SendRequest` based on a given `idHash`.

  ```solidity
  function getSendRequest(
      uint256 idHash
  ) public view returns (SendRequest memory);
  ```
* **getNonce**: This function returns the nonce of a given account.

  ```solidity
  function getNonce(address account) public view returns (uint256);
  ```
* **deposit**: This function deposits an amount of a specific ERC20 token from the sender's address into the contract and updates the sender's private and hash balances. A zkSNARKs proof and its corresponding input are required for this operation to ensure confidentiality.

  ```solidity
  function deposit(
      address denomination,
      uint256 amount,
      string memory privateNewBalance,
      bytes calldata proof,
      uint[3] memory input
  );
  ```
* **withdraw**: This function withdraws an amount of a specific ERC20 token from the contract to the sender's address and updates the sender's private and hash balances. A zkSNARKs proof and its corresponding input are required for this operation to ensure confidentiality.

  ```solidity
  function withdraw(
      address denomination,
      uint256 amount,
      string memory privateNewBalance,
      bytes calldata proof,
      uint[5] memory input
  ); 
  ```
* **createRequest**: This function creates multiple `SendRequest` using an array of `CreateRequestMessage`. It also updates the sender's private and hash balances for each request.

  ```solidity
  function createRequest(
      CreateRequestMessage[] memory cr
  );
  ```
* **acceptRequest**: This function is used to accept a `SendRequest`. The function takes the `idHash` of the `SendRequest`, the new private balance of the receiver, a zkSNARKs proof and its corresponding inputs as arguments. It verifies the proof, checks if the request is valid and active, and then updates the private and hash balances of the receiver.

  ```solidity
  function acceptRequest(
      uint256 idHash,
      string memory privateNewBalance,
      bytes calldata proof,
      uint[3] memory input
  );
  ```


# Deal

## ConfidentialDeal Contract

The `ConfidentialDeal` contract is a significant component of the NotVault SDK. It primarily extends the ERC721 functionality to implement confidential deals that interact with a Confidential Vault and supports the verification of zkSNARKs proofs to maintain privacy. This contract leverages OpenZeppelin contracts for various functionalities such as ERC721, pausable, ownable, and burnable features.

### Structure Definitions

* **DealMeta**: This structure contains the metadata of a deal, including owner, counterpart, denomination, name, description, notional, and initial.

### Public Functions

* **pause** and **unpause**: These functions allow the owner of the contract to pause and unpause the contract respectively.
* **tokenURI**: This function returns the URI of the token based on the token ID.
* **safeMint**: This function allows the owner to mint a token safely. The token metadata (URI) and other deal-specific data (counterpart, minimum commitment, and idHash) are associated with the token during minting. The nonce for the owner and the counterpart is incremented, and the token is added to the owner and counterpart's pool.

```solidity
function safeMint(
    address counterpart,
    uint256 minCommitment,
    uint256 idHash,
    string memory uri
) 
public 
returns (uint256);
```

* **getDealByOwner**: This function returns all the deals initiated by a given owner.

```solidity
function getDealByOwner(
    address owner
) 
public 
view 
returns (
    DealStruct[] memory
)
```

* **getDealByCounterpart**: This function returns all the deals where a given address is the counterpart.

```solidity
function getDealByCounterpart(
    address counterpart
) 
public 
view 
returns (
    DealStruct[] memory
);
```

* **getSendRequestByDeal**: This function returns all the SendRequests associated with a given deal.

```solidity
function getSendRequestByDeal(
    uint256 tokenId
) 
public 
view 
returns (
    SendRequest[] memory
);
```

* **addSendRequest**: This function allows associating a SendRequest to a deal using its `idHash`.

```solidity
function addSendRequest(
    uint256 tokenId,
    uint256 idHash
)
public;
```

* **accept**: This function allows the counterpart of a deal to accept it. The function verifies the zkSNARKs proof, checks the minimum commitment, and compares the idHash before marking the deal as accepted.

```solidity
function accept(
    uint256 tokenId,
    bytes calldata proof,
    uint[3] memory input
)
public;
```


# Oracle

## ConfidentialOracle Contract

The `ConfidentialOracle` contract provides functionalities to store and retrieve arbitrary key-value data from a confidential mapping. A zkSNARKs proof is required to set the values, ensuring privacy and security.

### Public Functions

* **getValue**: This function returns the value stored against a given key for a particular owner.

```solidity
function getValue(
    address owner,
    uint256 key
) 
public view 
returns (uint256);
```

* **setValue**: This function allows an owner to set a value against a key in the mapping. The function verifies the zkSNARKs proof before updating the value.

```solidity
function setValue(
    bytes calldata proof,
    uint[2] memory input
)
public;
```


# Service Bus

## Overview of the ConfidentialServiceBus Contract

The `ConfidentialServiceBus` is a critical part of the NotVault SDK. Its core functionality lies in providing a confidential service bus that makes use of a zkSNARK verifier to ensure the creator of the message knows the value of the hash being published.

### Contract Structure

The `ConfidentialServiceBus` contract encompasses the following main components:

1. **Events**:
   * `set_value`: An event emitted when a new value is set, including the owner's address, the key, the value, and the block timestamp.
2. **Functions**:
   * `getValue`: A view function that retrieves a value from `valuesMap` using an owner's address and a key.
   * `setValue`: A function that verifies a zkSNARK proof and then sets a value in the `valuesMap`. It emits the `set_value` event.

### Functions Description

* **getValue Function**

  This function retrieves a value from the `valuesMap` for a given owner and a key. It is a view function and hence does not alter the state of the contract. The function signature is as follows:

  ```solidity
  function getValue(address owner, uint256 key) public view returns (uint256);
  ```
* **setValue Function**

  This function sets a value in the `valuesMap` after verifying a provided zkSNARK proof. It emits a `set_value` event that contains the owner's address, the key, the value, and the block timestamp. The function signature is:

  ```solidity
  function setValue(bytes calldata proof, uint[2] memory input) public;
  ```

This contract provides a confidential service bus using the power of zkSNARKs and an EVM compatible blockchain. This approach ensures that the data's integrity is maintained while keeping the original value confidential, hence the name `ConfidentialServiceBus`.


# Circuits

The infrastructure depends on five  [zkSNARK](https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof) circuits - `DataVerifier`, `HashApprover`, `HashMinCommitment`, `HashReceiver`, and `HashSender` to maintain data integrity and secure verification in the ecosystem.


# DataVerifier

The `DataVerifier` circuit is a  [zkSNARK](https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof)s circuit is responsible for verifying certain constraints over the provided data and returning hash values for further usage.

### Template Parameters

The circuit is defined with two parameters:

* **tLevel**: Total number of data entries.
* **nLevel**: Number of data entries with constraints.

```circom
template DataVerifier (tLevel, nLevel) { /*...*/ }
```

### Input Signals

The circuit takes in the following input signals:

* **data**: An array of `tLevel + nLevel` size, which contains the data entries that the circuit will process.
* **code**: An array of `tLevel + nLevel` size, which serves as a form of mask for the data.
* **constraint\_upper**: An array of `nLevel` size, which specifies the upper bound for the respective data entry.
* **constraint\_lower**: An array of `nLevel` size, which specifies the lower bound for the respective data entry.

```circom
signal input data[tLevel + nLevel];
signal input code[tLevel + nLevel];
signal input constraint_upper[nLevel];
signal input constraint_lower[nLevel];
```

### Output Signals

The circuit produces two output signals:

* **idHash**: A 2-element array which holds the hash of the `data` input signal.
* **constraintHash**: A 2-element array which holds the hash of the data entries with constraints.

```circom
signal output idHash[2];
signal output constraintHash[2];
```

### Components

* **comp\_upper**: An array of `GreaterEqThan` components of `nLevel` size that checks if each constrained data entry is greater or equal to its respective upper constraint.
* **comp\_lower**: An array of `LessEqThan` components of `nLevel` size that checks if each constrained data entry is less or equal to its respective lower constraint.
* **hasher**: A `Pedersen` hashing component that hashes the `data` input signal.
* **chasher**: A `Pedersen` hashing component that hashes the data entries with constraints.

```circom
component comp_upper[nLevel];
component comp_lower[nLevel];
component hasher = Pedersen(tLevel + nLevel);
component chasher = Pedersen(tLevel);
```

### Inclusion of External Circuits

The circuit makes use of the `comparators` and `pedersen` circuits from the `circomlib` library.

```circom
include "../../node_modules/circomlib/circuits/comparators.circom";
include "../../node_modules/circomlib/circuits/pedersen.circom";
```

### BitSize Variable

A variable `bitSize` is declared and initialized with `36`. This bitSize is the maximum bit length of data the `GreaterEqThan` and `LessEqThan` components can handle.

```circom
// max size = 68,719,476,735 (68.7b)
var bitSize = 36;
```


# HashApprover

The `HashApprover`  is a  [zkSNARK](https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof)s circuit is responsible for generating the hash of a key-value pair using the Poseidon hash function.

### Input Signals

The circuit takes in the following input signals:

* **key**: Represents the key for which the hash will be generated.
* **value**: Represents the value that is paired with the key for the hash generation.

```circom
signal input key;
signal input value;
```

### Output Signals

The circuit produces two output signals:

* **hash**: The generated hash of the input key-value pair.
* **keyOut**: A pass-through of the input key signal.

```circom
signal output hash;
signal output keyOut;
```

### Components

* **hasher**: A `Poseidon` hashing component that takes two inputs: key and value, and outputs the hash.

```circom
component hasher = Poseidon(2);
hasher.inputs[0] <== key;
hasher.inputs[1] <== value;
hash <== hasher.out;
```

### Inclusion of External Circuits

The circuit makes use of the `poseidon` circuit from the `circomlib` library.

```circom
include "../../node_modules/circomlib/circuits/poseidon.circom";
```

### Main Component

The main component of this circuit file is the `HashApprover` template.

```circom
component main = HashApprover();
```

This circuit is straightforward and primarily used for hashing a key-value pair using the Poseidon hash function and passing through the key. The output hash can be used for further data verification processes, while the output key can be used for mapping and data storage purposes.


# HashMinCommitment

The `HashMinCommitment` circuit is designed for generating hashed commitments and ensuring a certain amount is greater than or equal to a specified minimum amount.

### Input Signals

This circuit accepts the following input signals:

1. **amount**: This represents the amount under consideration.
2. **minAmount**: The minimum amount threshold.
3. **oracle\_owner**: Identifier for the owner of the oracle.
4. **oracle\_key**: Key for data retrieval in the oracle.
5. **oracle\_value**: The associated value with the oracle\_key.
6. **unlock\_sender**: Identifier for the sender in the unlock operation.
7. **unlock\_receiver**: Identifier for the receiver in the unlock operation.

```typescript
signal input amount;
signal input minAmount;
signal input oracle_owner;
signal input oracle_key;
signal input oracle_value;
signal input unlock_sender;
signal input unlock_receiver;
```

### Output Signals

This circuit outputs the following signals:

1. **amountHash**: Hash of the input amount.
2. **minAmountHash**: Hash of the minimum amount.
3. **idHash**: A complex hash, generated from all the input signals.

```circom
signal output amountHash;
signal output minAmountHash;
signal output idHash;
```

### Components

The circuit has several components:

* **comp1**: A comparator that checks if the `amount` is greater than or equal to the `minAmount`.

```circom
component comp1 = GreaterEqThan(252);
comp1.in[0] <== amount;
comp1.in[1] <== minAmount;
comp1.out === 1;
```

* **hashAmount**: A `Poseidon` hash function to hash the `amount`.

```circom
component hashAmount = Poseidon(1);
hashAmount.inputs[0] <== amount;
amountHash <== hashAmount.out;
```

* **hashMinAmount**: A `Poseidon` hash function to hash the `minAmount`.

```circom
component hashMinAmount = Poseidon(1);
hashMinAmount.inputs[0] <== minAmount;
minAmountHash <== hashMinAmount.out;
```

* **hashId**: A `Poseidon` hash function to hash all input signals to generate the `idHash`.

```circom
component hashId = Poseidon(6);
hashId.inputs[0] <== amount;
hashId.inputs[1] <== oracle_owner;
hashId.inputs[2] <== oracle_key;
hashId.inputs[3] <== oracle_value;
hashId.inputs[4] <== unlock_sender;
hashId.inputs[5] <== unlock_receiver;
idHash <== hashId.out;
```

### Inclusion of External Circuits

The circuit includes `poseidon` and `comparators` circuits from the `circomlib` library.

```circom
include "../../node_modules/circomlib/circuits/poseidon.circom";
include "../../node_modules/circomlib/circuits/comparators.circom";
```

### Main Component

The main component of this circuit file is the `HashMinCommitment` template.

```circom
component main = HashMinCommitment();
```

The `HashMinCommitment` circuit is used primarily for creating hashed commitments for amounts while enforcing that the amount is greater than or equal to the minimum threshold. The hashed outputs can be used for comparison and verification processes in other parts of your application.


# HashReceiver

The `HashReceiver` circuit is intended for handling and validating the transfer of amounts to a receiver. It creates hashed versions of the amount transferred and the balance of the receiver before and after the transfer.

### Input Signals

The circuit takes the following inputs:

1. **amount**: The amount to be transferred to the receiver.
2. **receiverBalanceBeforeTransfer**: The receiver's balance before the transfer occurs.

```circom
signal input amount;  
signal input receiverBalanceBeforeTransfer;
```

### Output Signals

The circuit outputs the following signals:

1. **receiverBalanceBeforeTransferHash**: The hash of the receiver's balance before the transfer occurs.
2. **receiverBalanceAfterTransferHash**: The hash of the receiver's balance after the transfer has occurred.
3. **amountHash**: The hash of the amount that is transferred.

```circom
signal output receiverBalanceBeforeTransferHash;
signal output receiverBalanceAfterTransferHash;
signal output amountHash;
```

### Components

The circuit utilizes the following components:

* **comp1**: A comparator to ensure that the `amount` is greater than or equal to zero.

```circom
component comp1 = GreaterEqThan(252);
comp1.in[0] <== amount;
comp1.in[1] <== 0;
comp1.out === 1;
```

* **hashAmount**: A `Poseidon` hashing function to create a hash of the `amount`.

```circom
component hashAmount = Poseidon(1);
hashAmount.inputs[0] <== amount;
amountHash <== hashAmount.out;
```

* **hashBeforeBalance**: A `Poseidon` hashing function to create a hash of the receiver's balance before the transfer.

```circom
component hashBeforeBalance = Poseidon(1);
hashBeforeBalance.inputs[0] <== receiverBalanceBeforeTransfer;
receiverBalanceBeforeTransferHash <== hashBeforeBalance.out;
```

* **hashAfterBalance**: A `Poseidon` hashing function to create a hash of the receiver's balance after the transfer.

```circom
component hashAfterBalance = Poseidon(1);
hashAfterBalance.inputs[0] <== receiverBalanceBeforeTransfer + amount;
receiverBalanceAfterTransferHash <== hashAfterBalance.out;
```

### External Circuit Inclusions

The circuit includes `poseidon` and `comparators` circuits from the `circomlib` library.

```circom
include "../../node_modules/circomlib/circuits/poseidon.circom";
include "../../node_modules/circomlib/circuits/comparators.circom";
```

### Main Component

The main component of this circuit file is the `HashReceiver` template.

```circom
component main = HashReceiver();
```

The `HashReceiver` circuit is used primarily for creating hashed versions of the amount being transferred and the receiver's balance before and after the transfer. This can be used for transaction verification and integrity checks within your application.


# HashSender

The `HashSender` circuit is designed to process and validate transfers from a sender, creating hashed versions of the amount transferred, the balance of the sender before and after the transfer, a nonce for transaction uniqueness, and a combined identifier hash.

### Input Signals

The circuit accepts the following inputs:

1. **sender**: The sender of the transaction.
2. **senderBalanceBeforeTransfer**: The balance of the sender before the transaction.
3. **amount**: The amount to be transferred.
4. **nonce**: A unique identifier for each transaction.

```circom
signal input sender;
signal input senderBalanceBeforeTransfer;
signal input amount;  
signal input nonce;
```

### Output Signals

The circuit outputs the following signals:

1. **senderBalanceBeforeTransferHash**: The hash of the sender's balance before the transfer occurs.
2. **senderBalanceAfterTransferHash**: The hash of the sender's balance after the transfer has occurred.
3. **amountHash**: The hash of the amount that is transferred.
4. **nonceVerification**: The nonce input passed straight through for verification.
5. **idHash**: The hash of a combination of sender, sender balance before transfer, amount, and nonce.

```circom
signal output senderBalanceBeforeTransferHash;
signal output senderBalanceAfterTransferHash;
signal output amountHash;
signal output nonceVerification;
signal output idHash;
```

### Components

The circuit incorporates the following components:

* **comp1**: A comparator ensuring that the `amount` is greater than or equal to zero.

```circom
component comp1 = GreaterEqThan(252);
comp1.in[0] <== amount;
comp1.in[1] <== 0;
comp1.out === 1;
```

* **comp2**: A comparator checking if the `senderBalanceBeforeTransfer` is greater than or equal to the `amount`.

```circom
component comp2 = GreaterEqThan(252);
comp2.in[0] <== senderBalanceBeforeTransfer;
comp2.in[1] <== amount;
comp2.out === 1;
```

* **hashAmount**: A `Poseidon` hashing function to create a hash of the `amount`.

```circom
component hashAmount = Poseidon(1);
hashAmount.inputs[0] <== amount;
amountHash <== hashAmount.out;
```

* **hashBeforeBalance**: A `Poseidon` hashing function to create a hash of the sender's balance before the transfer.

```circom
component hashBeforeBalance = Poseidon(1);
hashBeforeBalance.inputs[0] <== senderBalanceBeforeTransfer;
senderBalanceBeforeTransferHash <== hashBeforeBalance.out;
```

* **hashAfterBalance**: A `Poseidon` hashing function to create a hash of the sender's balance after the transfer.

```circom
component hashAfterBalance = Poseidon(1);
hashAfterBalance.inputs[0] <== senderBalanceBeforeTransfer - amount;
senderBalanceAfterTransferHash <== hashAfterBalance.out;
```

* **hashId**: A `Poseidon` hashing function to create a hash of a combination of sender, sender balance before transfer, amount, and nonce.

```circom
component hashId = Poseidon(4);
hashId.inputs[0] <== sender;
hashId.inputs[1] <== senderBalanceBeforeTransfer;
hashId.inputs[2] <== amount;
hashId.inputs[3] <== nonce;
idHash <== hashId.out;
```

### External Circuit Inclusions

The circuit includes `poseidon` and `comparators` circuits from the `circomlib` library.

```circom
include "../../

node_modules/circomlib/circuits/poseidon.circom";
include "../../node_modules/circomlib/circuits/comparators.circom";
```

### Main Component

The main component of this circuit file is the `HashSender` template.

```circom
component main = HashSender();
```

The `HashSender` circuit is primarily used for hashing important aspects of a transaction from a sender, which includes the amount transferred, the sender's balance before and after the transfer, a nonce for each transaction, and a combined identifier hash. This allows for secure, reliable transaction verification and integrity checks within your application.


