# Welcome

Welcome to 4thTech, Web3's first "on-chain" communication building blocks. Technology infrastructure that enables 1000s of "on-chain" communication dApps.

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


# Getting started

Learn about immutable on-chain communication, build on top of our protocol stack or utilize the power of our dMail & dChat SDKs & white labels.

Learn about permissionless, self-custodial & immutable on-chain communication, build on top of our OCC (i.e. on-chain communication) protocol stack or utilize the power of our SDKs & white labels.

<a href="/pages/xytkVfJISnvZ6jz7sOif" class="button primary" data-icon="gear">SDK</a>&#x20;

<a href="/pages/OFLrecusFEZ5nl5fTdwp" class="button primary" data-icon="browser">White-label</a>

This documentation library serves as a guide for developers and solutions users that are getting started with 4thTech. The documentation library also serves as a location to explore and understand the solutions and all the different resources available to assist with integration or system usage.

***

### Overview

4thTech is a Block Labs project built as a Web3 infrastructure technology framework, that aims to empower decentralized communication that can enable 1000s of dApps to evolve on Web3.

***

### Core primitives

While various use cases are possible, let's use dMail and dChat as examples. The dChat W2W message exchange happens on-chain as one short message represents one L1 or L2 blockchain transaction. As dMail is data heavier, lite encrypted JSON objects are created to hold dMail metadata. The link to this metadata and checksum is recorded on the chain as a blockchain transaction. The same goes for W2W data file transfers where; 1 data file package transfer = 1 L1/L2-TX. So again, the core primitive described by the formula below applies;

{% hint style="info" %}
**Formula:** 1 email/message/data-exchange = 1 L1/L2-TX
{% endhint %}

Every wallet becomes an on-chain identity, and the message or data vault can be accessible (i.e. decrypted) only with users' private keys!

There are three encryption options available within the protocol:

* custom encryption
* AES - randomly generated secret key (i.e. Advanced Encryption Standard)
* AES - secret key produced by ECDH (i.e. Elliptic-Curve Diffie-Hellman)

{% hint style="info" %}
**Formula:** not your keys = not your email/message/data
{% endhint %}


# Overview

Read about 4thTech architecture overview. Designed to be as lightweight and modular as possible while retaining core decentralization primitives.

The OCC Framework architecture was designed to be as lightweight and modular as possible while retaining core decentralization primitives. No personal data whatsoever is collected, while the only party with access to communication data is the user himself. Code is law principle applies! Connected by the OCC SDK, four main legos complete the on-chain communication framework:

1. the OCC Protocol,
2. blockchain network,
3. encryption,
4. decentralized storage.

![Infrastructural layer](https://raw.githubusercontent.com/4thtech/static-assets/main/image/infrastructural-layer-schematic-4thtech-v4.svg)


# Blockchain

We strive to enable access to on-chain communication no matter to the native L1 or L2.

With the emergence of blockchain and smart contracts, new ways are allowing innovative use cases to be developed. In the case of 4thTech, communication protocols were developed, enabling secure, permissionless and immutable communication.

In the case of 4thTech, blockchain transactions are used for on-chain data and message exchange as one communication package (i.e. email, short message or data file transfer) represents one L1/L2 transaction. Blockchain acts as an underlying network infrastructure enabling immutability and transparency of the communication transactions executed by the 4thTech protocols.


# Storage

While the SDK integrators can utilize centralized storage, decentralized storage is the key to any modern Web3 solution.

There are four storage databases forming within the framework:

1. If we take a look at the dMail and dChat as an example, blockchain is used to store:
   * A link to the dMail JSON metadata, timestamp, checksum & sender address,
   * dChat encrypted message, timestamp & sender address.
2. The concept of decentralized storage is used for the temporary or permanent storage of encrypted communication and data files and JSON files (i.e. dMail, subject & content attachment location).
3. Integrators can also opt for more centralised storage such as cloud storage.
4. User local storage is used for storing:
   * wallet private keys,
   * dMail & dChat content hash, and
   * user-initiated backup of conversations, data files and reports.


# OCC Protocol

With many iterations behind there are six smart contracts forming the core protocol layer.

With many iterations behind there are six smart contracts forming the core protocol layer:

* **Mails**: Handles email-like messaging on the EVM
* **Chat**: Provides a decentralized chat functionality on the EVM
* **Users**: Manages user information (encryption public keys)
* **AppFeeManager**: Manages fees and apps registration
* **TierManager**: Manages tiers and fees discount
* **Lock**: Locks ERC20 tokens for a specific period of time


# Encryption

Read about 4thTech encryption overview.

Encryption is one of the key parts of the infrastructure. There are three options available:

1. **Custom encryption**

   Integrators have the option to develop their own specific encryption implementations.
2. **AES**

   Natively AES-256-GCM (i.e. Advanced Encryption Standard) is used for the encryption algorithm. The secret key can be randomly generated or imported.
3. **AES - ECDH** (i.e. Elliptic-Curve Diffie-Hellman)

   Natively AES-256-GCM is used for the encryption algorithm. The secret key is produced with ECDH secret key exchange. The sender needs the receiver [Encryptor extension](https://chrome.google.com/webstore/detail/encryptor/feolajpinjjfikmmeknkdjbllbppojij) public key to be recorded on the blockchain. Encryptor extension is used to calculate the shared secret key.


# SDK

dMail & dChat plug-and-play SDKs stand ready for security-enabled social scaling in the multi-chain universe

We've made a Typescript/Javascript SDK that makes it easier for you to work with the Protocol smart contracts, storage providers, encryption methods, and our [Encryptor Extension](https://chrome.google.com/webstore/detail/encryptor/feolajpinjjfikmmeknkdjbllbppojij).

To view our SDK source code you can see at [SDK GitHub](https://github.com/4thtech/sdk-js) page.

To begin, we recommend looking at our documentation which include specifications and code examples. These documentation will help you better understand how to use the SDK and integrate it into your application.

SDK packages:

* [@4thtech-sdk/ethereum](/sdk/ethereum)
* [@4thtech-sdk/encryption](/sdk/encryption)
* [@4thtech-sdk/encryptor](/sdk/encryptor)
* [@4thtech-sdk/storage](/sdk/storage)
* [@4thtech-sdk/types](/sdk/types)


# White-label

dMail & dChat white-label UI stand ready for security-enabled social scaling in the multi-chain universe

We have prepared a white-label framework for dMail & dChat to enable quick and easy builds. This framework uses a modern, minimalist design style that emphasizes simplicity. It comes with an intuitive and effective navigation and setup system. To ensure the best possible user experience, we have developed a user interface that provides step-by-step setup instructions.

To use and build on top of our white-label you can fork our [GitHub repository](https://github.com/4thtech/white-label-client) and start experimenting.


# Ethereum

Documentation for the @4thtech-sdk/ethereum package

This package provides functionalities to interact with 4thTech protocol on Ethereum blockchain.

### Installation

```bash
npm install @4thtech-sdk/ethereum
```

### Core Classes

* [Mail](https://github.com/4thtech/wiki.4thtech.io/blob/main/docs/sdk/ethereum/mail/README.md): Class that handles sending, retrieving and listening for events related to mail on-chain storage.
* [Chat](https://github.com/4thtech/wiki.4thtech.io/blob/main/docs/sdk/ethereum/chat/README.md): Class that handles sending, retrieving and listening for events related to chat on-chain storage.
* [Encryptor](https://github.com/4thtech/wiki.4thtech.io/blob/main/docs/sdk/ethereum/encryptor/README.md): Class that provides functionality for public key retrieval and storage, as well as shared secret key computation using the Encryptor extension.


# Mail

Class that handles sending, retrieving and listening for events related to mail on-chain storage.

### Usage

Below is a minimal example of how to initialize Mail (with no optional parameters). It's highly recommended to also use your own appId.

```ts
import { Mail } from '@4thtech-sdk/ethereum';

const mail = new Mail({
  walletClient,
  remoteStorageProvider,
});
```

### Parameters

#### config

* **Type** `MailConfig`

The configuration object required to initialize the mail client.

#### config.walletClient

* **Type** `WalletClient`

An instance of the wallet client that takes care of sending Ethereum transactions.

#### config.remoteStorageProvider

* **Type** `RemoteStorageProvider`

An instance of the remote storage provider for storing and retrieving mail-related data stored off-chain such as metadata and attachments.

#### config.appId (Optional)

* **Type** `AppId`
* **Default** `0x0000000000000000000000000000000000000000000000000000000000000000`

A unique identifier for your application.

Application ID is used to effectively store and retrieve mails based on ID. Without an assigned App ID, it defaults to "zero". When multiple apps uses the same ID, all mails are shared in all those apps. Problem can appear if some of those apps uses encryption or remote storage provider that is not supported by your app. Those mails then can't be retrieved/decrypted.

On top of that, if you register your own app, you can set up an integrator fee which will be charged on every sent mail.

```ts
const mail = new Mail({
  walletClient,
  remoteStorageProvider,
  appId,
});
```

#### config.encryptionHandler (Optional)

* **Type** `EncryptionHandler`

The handler used for decrypting mails.

To manage encrypted emails effectively, ensure you provide a `EncryptionHandler` instance. This instance must include all encryption types used by your app. Without this, encrypted emails cannot be decrypted.

```ts
const mail = new Mail({
  walletClient,
  remoteStorageProvider,
  encryptionHandler,
});
```


# send

Send a new mail.

### Usage

Below is a minimal example of how to use send method (with no optional parameters). It's highly recommended to also use encryption.

```ts
const txResponse = await mail.send({
  envelope,
});
```

### Returns

`Promise<EthereumTransactionResponse>`

A promise that resolves to the response from the `sendTransaction` method on the `walletClient` provided by the developer on `Mail` initialization.

### Parameters

#### options

* **Type** `MailSendOptions`

Configuration for sending mail.

#### options.envelope

* **Type** `Envelope`

The mail envelope to send.

```ts
import type { Envelope } from '@4thtech-sdk/types';

const envelope: Envelope = {
  content: {
    subject: 'Test subject',
    body: 'Test body...', // optional
    attachments: [], // optional
  },
  receiver: '0x...',
};
```

#### options.encryption (Optional)

* **Type** `Encryption`

The encryption method to apply to the mail.

```ts
const txResponse = await mail.send({
  envelope,
  encryption,
});
```

#### options.onStateChange (Optional)

* **Type** `(state: MailSendState) => void`

A callback function to track state changes during the sending process.

```ts
import type { MailSendState } from '@4thtech-sdk/types';

const txResponse = await mail.send({
  envelope,
  onStateChange: (state: MailSendState) => {
    console.log(state);
  },
});
```

`MailSendState` is an enum of the possible states of the sending process.

* When sending non-encrypted mail
  * STORING\_ATTACHMENTS
  * STORING\_ENVELOPE
  * SENDING\_TRANSACTION
* When sending encrypted mail
  * ENCRYPTING\_STORING\_ATTACHMENTS
  * ENCRYPTING\_STORING\_ENVELOPE
  * SENDING\_TRANSACTION

#### options.onUploadProgress (Optional)

* **Type** `(progressInfo: FileProgressInfo) => void`

A callback function to track the progress of file uploads when sending the mail.

```ts
import type { FileProgressInfo } from '@4thtech-sdk/types';

const txResponse = await mail.send({
  envelope,
  onUploadProgress: (progressInfo: FileProgressInfo) => {
    console.log(`Upload Progress (${progressInfo.fileName}): ${progressInfo.percent}%`);
  },
});
```


# setOpenedAt

Set opened time for a specific mail. This method can only be performed by the receiver of the mail.

### Usage

```ts
const mailIndex = 1n;
const txResponse = await mail.setOpenedAt(mailIndex);
```

### Returns

`Promise<EthereumTransactionResponse>`

A promise that resolves to the response from the `sendTransaction` method on the `walletClient` provided by the developer on `Mail` initialization.

### Parameters

#### mailIndex

* **Type** `bigint`

The index of the mail for which the opened time needs to be set.


# deleteMail

Deletes a specific mail. This method can only be performed by the receiver of the mail.

### Usage

```ts
const mailIndex = 1n;
const txResponse = await mail.deleteMail(mailIndex);
```

### Returns

`Promise<EthereumTransactionResponse>`

A promise that resolves to the response from the `sendTransaction` method on the `walletClient` provided by the developer on `Mail` initialization.

### Parameters

#### mailIndex

* **Type** `bigint`

The index of the mail to be deleted.


# deleteMails

Deletes multiple mails. This method can only be performed by the receiver of the mails.

### Usage

```ts
const mailIndexes = [1n, 2n];
const txResponse = await mail.deleteMails(mailIndexes);
```

### Returns

`Promise<EthereumTransactionResponse>`

A promise that resolves to the response from the `sendTransaction` method on the `walletClient` provided by the developer on `Mail` initialization.

### Parameters

#### mailIndexes

* **Type** `bigint[]`

The indexes of the mails to be deleted.


# fetch

Fetch a specific mail.

### Usage

```ts
const receiver = '0x...';
const mailIndex = 1n;
const receivedEnvelope = await mail.fetch(receiver, mailIndex);
```

### Returns

`Promise<ReceivedEnvelope>`

A promise that resolves to the received mail Envelope.

### Parameters

#### receiver

* **Type** `Address`

The mail receiver's address.

#### mailIndex

* **Type** `bigint`

The index of the mail to be fetched.


# fetchAll

Fetch all mails for a specific receiver.

### Usage

```ts
const receiver = '0x...';
const receivedEnvelopes = await mail.fetchAll(receiver);
```

### Returns

`Promise<ReceivedEnvelope[]>`

A promise that resolves to an array of received mail Envelopes.

### Parameters

#### receiver

* **Type** `Address`

The mail receiver's address.


# fetchPaginated

Fetch mails in a paginated manner for a specific receiver. This can be helpful when dealing with a large number of mails, as it allows you to load and process a manageable number of mails at a time.

### Usage

```ts
const receiver = '0x...';
const pageNumber = 1n;
const pageSize = 10n;
const receivedEnvelopes = await mail.fetchAll(receiver, pageNumber, pageSize);
```

### Returns

`Promise<ReceivedEnvelope[]>`

A promise that resolves to an array of received mail Envelopes.

### Parameters

#### receiver

* **Type** `Address`

The mail receiver's address.

#### pageNumber

* **Type** `bigint`

The number of the page to be fetched.

#### pageSize

* **Type** `bigint`

The size of the page (i.e., the number of mails per page).


# fetchByTransactionHash

Fetch a mail using its associated transaction hash.

### Usage

```ts
const txHash = '0x...';
const receivedEnvelope = await mail.fetchByTransactionHash(txHash);
```

### Returns

`Promise<ReceivedEnvelope>`

A promise that resolves to the received mail Envelope associated with the specified transaction hash.

### Parameters

#### transactionHash

* **Type** `TransactionHash`

The transaction hash used to filter the associated mail.


# count

Counts the total number of mails associated with a specific receiver.

### Usage

```ts
const receiver = '0x...';
const numberOfMails = await mail.count(receiver);
```

### Returns

`Promise<bigint>`

A promise that resolves to the total number of mails for the specified receiver.

### Parameters

#### receiver

* **Type** `Address`

The mail receiver's address for which the mail count is being fetched.


# getUserAppIds

Retrieves the App IDs associated with a specific user.

### Usage

```ts
const user = '0x...';
const appIds = await mail.getUserAppIds(user);
```

### Returns

`Promise<AppId[]>`

A promise that resolves to an array of App IDs associated with the specified user.

### Parameters

#### user

* **Type** `Address`

The user's address for which the App IDs are being fetched.


# downloadAttachment

Downloads an attachment of a specific mail.

### Usage

```ts
const attachment = receivedEnvelope.content.attachments[0];
const fileBuffer = await mail.downloadAttachment(attachment);
```

### Returns

`Promise<ArrayBuffer>`

A promise that resolves to an array buffer of the downloaded file.

### Parameters

#### attachment

* **Type** `RemoteFileInfo`

The information about the attachment that needs to be downloaded.


# onNew

Sets up a listener for the event when a new mail is sent.

### Usage

```ts
const receiver = '0x...';
const sender = '0x...';

// Listen to received mails
mail.onNew(null, receiver, (envelope) => {
  console.log(envelope);
});

// Listen to sent mails
mail.onNew(sender, null, (envelope) => {
  console.log(envelope);
});

// Listen to all mails
mail.onNew(null, null, (envelope) => {
  console.log(envelope);
});
```

#### Stop watching

```ts
// Listen to received mails
const stopWatching = mail.onNew(null, receiver, (envelope) => {
  console.log(envelope);
});

// ... Later, to stop watching for the events
stopWatching();
```

### Returns

`UnwatchFn`

A function that can be invoked to stop watching for new event logs.

### Parameters

#### sender

* **Type** `Address | null`

The mail sender's address. If set to null, it listens for mails from any sender.

#### receiver

* **Type** `Address | null`

The mail receiver's address. If set to null, it listens for mails to any receiver.

#### callback

* **Type** `(envelope: ReceivedEnvelope) => void`

The callback function to be executed when a new mail event is detected. It receives a ReceivedEnvelope as its only argument.


# onOpened

Sets up a listener for the event when a mail is opened by the receiver.

### Usage

```ts
const receiver = '0x...';

mail.onOpened(receiver, null, (index, openedAt) => {
  console.log(index);
  console.log(openedAt);
});
```

#### Stop watching

```ts
const stopWatching = mail.onOpened(receiver, null, (index, openedAt) => {
  console.log(index);
  console.log(openedAt);
});

// ... Later, to stop watching for the events
stopWatching();
```

### Returns

`UnwatchFn`

A function that can be invoked to stop watching for new event logs.

### Parameters

#### receiver

* **Type** `Address | null`

The mail receiver's address. If set to null, it listens for any receiver.

#### index

* **Type** `bigint | null`

The index of the mail. If set to null, it listens for the opening of any mail.

#### callback

* **Type** `(index: bigint, openedAt: bigint) => void`

The callback function to be executed when a mail-opened event is detected. It receives the index of the opened mail and its opened timestamp as its arguments.


# onDeleted

Sets up a listener for the event when a mail is deleted by the receiver.

### Usage

```ts
const receiver = '0x...';

mail.onDeleted(receiver, null, (index, deletedAt) => {
  console.log(index);
  console.log(deletedAt);
});
```

#### Stop watching

```ts
const stopWatching = mail.onDeleted(receiver, null, (index, deletedAt) => {
  console.log(index);
  console.log(deletedAt);
});

// ... Later, to stop watching for the events
stopWatching();
```

### Returns

`UnwatchFn`

A function that can be invoked to stop watching for new event logs.

### Parameters

#### receiver

* **Type** `Address | null`

The mail receiver's address. If set to null, it listens for any receiver.

#### index

* **Type** `bigint | null`

The index of the mail. If set to null, it listens for the deletion of any mail.

#### callback

* **Type** `(index: bigint, deletedAt: bigint) => void`

The callback function to be executed when a mail-deleted event is detected. It receives the index of the deleted mail and its deletion timestamp as its arguments.


# Chat

Class that handles sending, retrieving and listening for events related to chat on-chain storage.

### Usage

Below is a minimal example of how to initialize Chat (with no optional parameters). It's highly recommended to also use your own appId.

```ts
import { Chat } from '@4thtech-sdk/ethereum';

const chat = new Chat({
  walletClient,
});
```

### Parameters

#### config

* **Type** `ChatConfig`

The configuration object required to initialize the chat client.

#### config.walletClient

* **Type** `WalletClient`

An instance of the wallet client that takes care of sending Ethereum transactions.

#### config.appId (Optional)

* **Type** `AppId`
* **Default** `0x0000000000000000000000000000000000000000000000000000000000000000`

A unique identifier for your application.

Application ID is used to effectively store and retrieve chat related data based on ID. Without an assigned App ID, it defaults to "zero". When multiple apps uses the same ID, all chat data are shared in all those apps.

If you register your own app, you can set up an integrator fee which will be charged on every sent message.

```ts
const chat = new Chat({
  walletClient,
  appId,
});
```

#### config.encryptor (Optional)

* **Type** `Encryptor`

A service that is optionally used for the encryption and decryption of chat messages.

If you wish to encrypt and decrypt chat messages, it's crucial to provide an `Encryptor` service for this purpose.

```ts
const chat = new Chat({
  walletClient,
  encryptor,
});
```


# sendMessage

Sends a message to a specified receiver.

### Usage

```ts
const receiver = '0x...';
const message = {
  content: 'Hello, this is a sample message.',
};
const txResponse = await chat.sendMessage(receiver, message);
```

### Returns

`Promise<EthereumTransactionResponse>`

A promise that resolves to the response from the `sendTransaction` method on the `walletClient` provided by the developer on `Chat` initialization.

### Parameters

#### receiver

* **Type** `Address`

The receiver's address to which the message will be sent.

#### message

* **Type** `Message`

The content of the message you want to send.

#### encryptMessage (Optional)

* **Type** `boolean`
* **Default** `true`

Determines whether the message should be encrypted before being sent. If not specified, the message will be encrypted by default.

```ts
const encryptMessage = false;
const txResponse = await chat.sendMessage(receiver, message, encryptMessage);
```


# addMessageToConversation

Adds a message to an existing conversation identified by a conversation hash.

### Usage

```ts
const conversationHash = '0x...';
const message = {
  content: 'Hello, this is a sample message.',
};
const txResponse = await chat.addMessageToConversation(conversationHash, message);
```

### Returns

`Promise<EthereumTransactionResponse>`

A promise that resolves to the response from the `sendTransaction` method on the `walletClient` provided by the developer on `Chat` initialization.

### Parameters

#### conversationHash

* **Type** `ConversationHash`

The unique identifier (hash) of the target conversation where the message will be added.

#### message

* **Type** `Message`

The content of the message you want to send.

#### encryptMessage (Optional)

* **Type** `boolean`
* **Default** `true`

Determines whether the message should be encrypted before being sent. If not specified, the message will be encrypted by default.

```ts
const encryptMessage = false;
const txResponse = await chat.addMessageToConversation(receiver, message, encryptMessage);
```


# deleteMessage

Deletes a specific message from an existing conversation identified by a conversation hash.

### Usage

```ts
const conversationHash = '0x...';
const messageIndex = 1n;
const txResponse = await chat.deleteMessage(conversationHash, messageIndex);
```

### Returns

`Promise<EthereumTransactionResponse>`

A promise that resolves to the response from the `sendTransaction` method on the `walletClient` provided by the developer on `Chat` initialization.

### Parameters

#### conversationHash

* **Type** `ConversationHash`

The unique identifier (hash) of the target conversation from which the message will be deleted.

#### index

* **Type** `bigint`

The position or index of the message you want to delete from the specified conversation. Make sure the index corresponds to the exact position of the message within the conversation.


# createGroupConversation

Creates a new group conversation with specified members, encryption settings, and member addition policies.

### Usage

```ts
const conversationName = 'Work Chat';
const isOnlyCreatorAllowedToAddMembers = true;
const isEncrypted = true;
const initialMembers = ['0xAddress1...', '0xAddress2...', '0xAddress3...'];

const txResponse = await chat.createGroupConversation(
  conversationName,
  isOnlyCreatorAllowedToAddMembers,
  isEncrypted,
  initialMembers,
);
```

### Returns

`Promise<EthereumTransactionResponse>`

A promise that resolves to the response from the `sendTransaction` method on the `walletClient` provided by the developer on `Chat` initialization.

### Parameters

#### conversationName

* **Type** `string`

The desired name for the new group conversation.

#### isOnlyCreatorAllowedToAddMembers

* **Type** `boolean`

Specifies whether only the creator of the group conversation can add new members. If set to true, other members cannot add participants to the group.

#### isEncrypted

* **Type** `boolean`

Determines if the group conversation should be encrypted. When set to true, all messages within the group will be encrypted.

#### members

* **Type** `Address[]`

An array of Ethereum addresses representing the initial members of the group conversation. Ensure that these addresses belong to valid participants you want to include in the group.


# removeConversation

Removes a conversation based on its unique hash identifier. This operation can be done only by the creator of the conversation.

### Usage

```ts
const conversationHash = '0x...';
const txResponse = await chat.removeConversation(conversationHash);
```

### Returns

`Promise<EthereumTransactionResponse>`

A promise that resolves to the response from the `sendTransaction` method on the `walletClient` provided by the developer on `Chat` initialization.

### Parameters

#### conversationHash

* **Type** `ConversationHash`

The unique hash identifier of the conversation you wish to remove.


# addMembersToGroupConversation

Adds members to an existing group conversation based on its unique hash identifier.

### Usage

```ts
const conversationHash = '0x...';
const members = ['0xAddress1...', '0xAddress2...'];
const txResponse = await chat.addMembersToGroupConversation(conversationHash, members);
```

### Returns

`Promise<EthereumTransactionResponse>`

A promise that resolves to the response from the `sendTransaction` method on the `walletClient` provided by the developer on `Chat` initialization.

### Parameters

#### conversationHash

* **Type** `ConversationHash`

The unique hash identifier of the target group conversation to which members will be added.

#### members

* **Type** `Address[]`

An array of Ethereum addresses representing the members you wish to add to the group conversation.


# removeMemberFromGroupConversation

Removes a specific member from an existing group conversation based on its unique hash identifier.

### Usage

```ts
const conversationHash = '0x...';
const memberToRemove = '0x...';
const txResponse = await chat.removeMemberFromGroupConversation(conversationHash, memberToRemove);
```

### Returns

`Promise<EthereumTransactionResponse>`

A promise that resolves to the response from the `sendTransaction` method on the `walletClient` provided by the developer on `Chat` initialization.

### Parameters

#### conversationHash

* **Type** `ConversationHash`

The unique hash identifier of the target group conversation from which a member will be removed.

#### member

* **Type** `Address`

The Ethereum address representing the member you wish to remove from the group conversation.


# removeMembersFromGroupConversation

Removes multiple members from an existing group conversation using its unique hash identifier.

### Usage

```ts
const conversationHash = '0x...';
const membersToRemove = ['0xAddress1...', '0xAddress2...'];
const txResponse = await chat.removeMembersFromGroupConversation(conversationHash, membersToRemove);
```

### Returns

`Promise<EthereumTransactionResponse>`

A promise that resolves to the response from the `sendTransaction` method on the `walletClient` provided by the developer on `Chat` initialization.

### Parameters

#### conversationHash

* **Type** `ConversationHash`

The unique hash identifier of the target group conversation from which members will be removed.

#### members

* **Type** `Address[]`

An array of Ethereum addresses representing the members you wish to remove from the group conversation.


# calculateConversationHash

Generates a unique conversation hash for a pair of account addresses, ensuring a consistent hash regardless of the order of the accounts provided.

### Usage

```ts
const address1 = '0xAddress1...';
const address2 = '0xAddress2...';
const conversationHash = chat.calculateConversationHash(address1, address2);
```

### Returns

`ConversationHash`

The uniquely generated conversation hash for the pair of provided account addresses.

### Parameters

#### account1

* **Type** `Address`

The first Ethereum account address used in generating the conversation hash.

#### account2

* **Type** `Address`

The second Ethereum account address used in generating the conversation hash.


# countMessages

Counts the total number of messages within a specific conversation.

### Usage

```ts
const conversationHash = '0x...';
const numberOfMessages = await chat.countMessages(conversationHash);
```

### Returns

`Promise<bigint>`

A promise that resolves to the total number of messages for the specified conversation.

### Parameters

#### conversationHash

* **Type** `ConversationHash`

The hash identifier of the target conversation for which the message count is being fetched.


# fetchConversationHashes

Fetches the conversation hashes associated with a specific account.

### Usage

```ts
const account = '0x...';
const conversationHashes = await chat.fetchConversationHashes(account);
```

### Returns

`Promise<ConversationHash[]>`

A promise that resolves to an array of conversation hashes that are related to the specified account.

### Parameters

#### account

* **Type** `Address`

The target account's address for which the related conversation hashes are being fetched.


# fetchConversation

Fetches the details of a conversation based on its hash.

### Usage

```ts
const conversationHash = '0x...';
const conversation = await chat.fetchConversation(conversationHash);
```

### Returns

`Promise<Conversation>`

A promise that resolves to the details of the conversation corresponding to the specified conversation hash.

### Parameters

#### conversationHash

* **Type** `ConversationHash`

The hash of the target conversation that you want to fetch the details for.


# fetchConversations

Fetches all the conversations associated with a specific account.

### Usage

```ts
const account = '0x...';
const conversations = await chat.fetchConversations(account);
```

### Returns

`Promise<Conversation[]>`

A promise that resolves to an array containing all the conversations associated with the specified account.

### Parameters

#### account

* **Type** `Address`

The address of the target account for which all related conversations are being fetched.


# fetchConversationMessagesPaginated

Fetches the messages of a specific conversation in a paginated manner.

### Usage

```ts
const conversationHash = '0x...';
const pageNumber = 1n;
const pageSize = 10n;
const messages = await chat.fetchConversationMessagesPaginated(
  conversationHash,
  pageNumber,
  pageSize,
);
```

### Returns

`Promise<ReceivedMessage[]>`

A promise that resolves to an array of messages from the specified conversation, corresponding to the provided page number and size.

### Parameters

#### conversationHash

* **Type** `ConversationHash`

The hash of the target conversation from which messages are being fetched.

#### pageNumber

* **Type** `bigint`

The number of the page to be fetched.

#### pageSize

* **Type** `bigint`

The size of the page (i.e., the number of messages per page).


# getUserAppIds

Retrieves the App IDs associated with a specific user.

### Usage

```ts
const user = '0x...';
const appIds = await chat.getUserAppIds(user);
```

### Returns

`Promise<AppId[]>`

A promise that resolves to an array of App IDs associated with the specified user.

### Parameters

#### user

* **Type** `Address`

The user's address for which the App IDs are being fetched.


# onMessageSent

Sets up a listener for when a new message is sent in a conversation.

### Usage

```ts
const sender = '0x...';
const conversationHash = '0x...';
const messageIndex = 99n;

// Listen to all messages sent by the sender
chat.onMessageSent(sender, null, null, (conversationHash, receivedMessage) => {
  console.log(conversationHash);
  console.log(receivedMessage);
});

// Listen to all messages sent to the conversation
chat.onMessageSent(null, conversationHash, null, (conversationHash, receivedMessage) => {
  console.log(conversationHash);
  console.log(receivedMessage);
});

// Listen to a specific message index
chat.onMessageSent(null, null, messageIndex, (conversationHash, receivedMessage) => {
  console.log(conversationHash);
  console.log(receivedMessage);
});
```

#### Stop watching

```ts
// Listen to all messages sent to the conversation
const stopWatching = chat.onMessageSent(
  null,
  conversationHash,
  null,
  (conversationHash, receivedMessage) => {
    console.log(conversationHash);
    console.log(receivedMessage);
  },
);

// ... Later, to stop watching for the events
stopWatching();
```

### Returns

`UnwatchFn`

A function that can be invoked to stop watching for new event logs.

### Parameters

#### sender

* **Type** `Address | null`

The message sender's address. If set to null, it listens for mails from any sender.

#### conversationHash

* **Type** `ConversationHash | null`

The hash of the target conversation. Set to null to listen to messages from any conversation.

#### index

* **Type** `bigint | null`

The index of the message in the conversation. Set to null to listen to messages at any index in a conversation.

#### callback

* **Type** `(conversationHash: ConversationHash, receivedMessage: ReceivedMessage) => void`

A callback function that will be executed when the new message sent event is detected. This callback is passed two arguments:

* `conversationHash`: The hash of the conversation the message belongs to.
* `receivedMessage`: The received message details.

The structure of receivedMessage is based on the type `ReceivedMessage`.


# onMessageDeleted

Sets up a listener for when a message is deleted from a conversation.

### Usage

```ts
const sender = '0x...';
const conversationHash = '0x...';
const messageIndex = 99n;

// Listen to all messages deleted by the sender
chat.onMessageDeleted(sender, null, null, (conversationHash, sender, index) => {
  console.log(conversationHash);
  console.log(sender);
  console.log(index);
});

// Listen to all messages deleted in the conversation
chat.onMessageDeleted(null, conversationHash, null, (conversationHash, sender, index) => {
  console.log(conversationHash);
  console.log(sender);
  console.log(index);
});

// Listen to a specific message index
chat.onMessageDeleted(null, null, messageIndex, (conversationHash, sender, index) => {
  console.log(conversationHash);
  console.log(sender);
  console.log(index);
});
```

#### Stop watching

```ts
// Listen to all messages deleted in the conversation
const stopWatching = chat.onMessageDeleted(
  null,
  conversationHash,
  null,
  (conversationHash, sender, index) => {
    console.log(conversationHash);
    console.log(sender);
    console.log(index);
  },
);

// ... Later, to stop watching for the events
stopWatching();
```

### Returns

`UnwatchFn`

A function that can be invoked to stop watching for new event logs.

### Parameters

#### sender

* **Type** `Address | null`

The sender's address of the deleted message. If set to null, it listens for deleted messages sent by any sender.

#### conversationHash

* **Type** `ConversationHash | null`

The hash of the target conversation from which the message was deleted. Set to null to listen to deleted messages from any conversation.

#### index

* **Type** `bigint | null`

The index of the message in the conversation that was deleted. Set to null to listen to deleted messages at any index in a conversation.

#### callback

* **Type** `(conversationHash: ConversationHash, sender: Address, index: bigint) => void`

A callback function that will be executed when the message deleted event is detected. This callback is passed two arguments:

* `conversationHash`: The hash of the conversation from which the message was deleted.
* `sender`: The Ethereum address of the sender of the deleted message.
* `index`: The index of the deleted message in the conversation.

The structure of the callback ensures that users are informed about which message (using the index) was deleted, who sent it, and from which conversation it was removed.


# onGroupConversationCreated

Sets up a listener for when a new group conversation is created.

### Usage

```ts
const creatorAddress = '0x...';

// Listen to all group conversations created by the specified sender
chat.onGroupConversationCreated(
  creatorAddress,
  (sender, conversationHash, conversationName, members) => {
    console.log(sender);
    console.log(conversationHash);
    console.log(conversationName);
    console.log(members);
  },
);

// Listen to all group conversations created by any sender
chat.onGroupConversationCreated(null, (sender, conversationHash, conversationName, members) => {
  console.log(sender);
  console.log(conversationHash);
  console.log(conversationName);
  console.log(members);
});
```

#### Stop watching

```ts
// Listen to all group conversations created by any sender
const stopWatching = chat.onGroupConversationCreated(
  null,
  (sender, conversationHash, conversationName, members) => {
    console.log(sender);
    console.log(conversationHash);
    console.log(conversationName);
    console.log(members);
  },
);

// ... Later, to stop watching for the events
stopWatching();
```

### Returns

`UnwatchFn`

A function that can be invoked to stop watching for new event logs.

### Parameters

#### sender

* **Type** `Address | null`

The group creator's address. If set to null, it listens for group conversations created by any sender.

#### callback

* **Type** `(sender: Address, conversationHash: ConversationHash, conversationName: string, members: Address[]) => void`

A callback function that will be executed when a new group conversation is detected. This callback is passed four arguments:

* `sender`: The creator's address.
* `conversationHash`: The hash of the created conversation.
* `conversationName`: The name of the group conversation.
* `members`: Array containing the addresses of the members of the created group conversation.


# onConversationRemoved

Sets up a listener for when a message is deleted from a conversation.

### Usage

```ts
const creatorAddress = '0x...';
const conversationHash = '0x...';

// Listen to all conversations removed by the specified sender
chat.onConversationRemoved(creatorAddress, null, (sender, conversationHash) => {
  console.log(sender);
  console.log(conversationHash);
});

// Listen to a specific conversation removed by any sender
chat.onConversationRemoved(null, conversationHash, (sender, conversationHash) => {
  console.log(sender);
  console.log(conversationHash);
});

// Listen to any conversation removal events
chat.onConversationRemoved(null, null, (sender, conversationHash) => {
  console.log(sender);
  console.log(conversationHash);
});
```

#### Stop watching

```ts
// Listen to any conversation removal events
const stopWatching = chat.onConversationRemoved(null, null, (sender, conversationHash) => {
  console.log(sender);
  console.log(conversationHash);
});

// ... Later, to stop watching for the events
stopWatching();
```

### Returns

`UnwatchFn`

A function that can be invoked to stop watching for new event logs.

### Parameters

#### sender

* **Type** `Address | null`

The conversation creator's address who deleted the conversation. If set to null, it listens for conversations removed by any sender.

#### conversationHash

* **Type** `ConversationHash | null`

The hash of the target conversation that got removed. If set to null, it listens for the removal of any conversation.

#### callback

* **Type** `(sender: Address, conversationHash: ConversationHash) => void`

A callback function that will be executed when a conversation removal event is detected. This callback is passed two arguments:

* `sender`: The creator's address who removed the conversation.
* `conversationHash`: The hash of the removed conversation.


# onMemberAddedToConversation

Sets up a listener for when a new member is added to a group conversation.

### Usage

```ts
const appId = '0x...';
const conversationHash = '0x...';
const newMemberAddress = '0x...';

// Listen to all members added to group conversations under a specific app
chat.onMemberAddedToConversation(appId, null, null, (appId, conversationHash, member) => {
  console.log(appId);
  console.log(conversationHash);
  console.log(member);
});

// Listen to all members added to a specific conversation
chat.onMemberAddedToConversation(
  null,
  conversationHash,
  null,
  (appId, conversationHash, member) => {
    console.log(appId);
    console.log(conversationHash);
    console.log(member);
  },
);

// Listen to a specific member being added to any group conversation
chat.onMemberAddedToConversation(
  null,
  null,
  newMemberAddress,
  (appId, conversationHash, member) => {
    console.log(appId);
    console.log(conversationHash);
    console.log(member);
  },
);
```

#### Stop watching

```ts
// Listen to all members added to a specific conversation
const stopWatching = chat.onMemberAddedToConversation(
  null,
  conversationHash,
  null,
  (appId, conversationHash, member) => {
    console.log(appId);
    console.log(conversationHash);
    console.log(member);
  },
);

// ... Later, to stop watching for the events
stopWatching();
```

### Returns

`UnwatchFn`

A function that can be invoked to stop watching for new event logs.

### Parameters

#### appId

* **Type** `AppId | null`

The App ID under which the group conversation is happening. If set to null, it listens for members added under any app.

#### conversationHash

* **Type** `ConversationHash | null`

The hash of the group conversation to which a new member is being added. If set to null, it listens for members added to any group conversation.

#### member

* **Type** `Address | null`

The address of the new member being added to the group conversation. If set to null, it listens for any member being added.

#### callback

* **Type** `(appId: AppId, conversationHash: ConversationHash, member: Address) => void`

A callback function that will be executed when a new member is added to a group conversation. This callback is passed three arguments:

* `appId`: The App ID under which the group conversation is happening.
* `conversationHash`: The hash of the group conversation to which the new member is being added.
* `member`: The address of the new member being added.


# onMemberRemovedFromConversation

Sets up a listener for when a member is removed from a group conversation.

### Usage

```ts
const appId = '0x...';
const conversationHash = '0x...';
const memberAddressToRemove = '0x...';

// Listen to all members removed from group conversations under a specific app
chat.onMemberRemovedFromConversation(appId, null, null, (appId, conversationHash, member) => {
  console.log(appId);
  console.log(conversationHash);
  console.log(member);
});

// Listen to all members removed from a specific conversation
chat.onMemberRemovedFromConversation(
  null,
  conversationHash,
  null,
  (appId, conversationHash, member) => {
    console.log(appId);
    console.log(conversationHash);
    console.log(member);
  },
);

// Listen to a specific member being removed from any group conversation
chat.onMemberRemovedFromConversation(
  null,
  null,
  memberAddressToRemove,
  (appId, conversationHash, member) => {
    console.log(appId);
    console.log(conversationHash);
    console.log(member);
  },
);
```

#### Stop watching

```ts
// Listen to all members removed from group conversations under a specific app
const stopWatching = chat.onMemberRemovedFromConversation(
  appId,
  null,
  null,
  (appId, conversationHash, member) => {
    console.log(appId);
    console.log(conversationHash);
    console.log(member);
  },
);

// ... Later, to stop watching for the events
stopWatching();
```

### Returns

`UnwatchFn`

A function that can be invoked to stop watching for new event logs.

### Parameters

#### appId

* **Type** `AppId | null`

The App ID under which the group conversation is taking place. If set to null, it listens for members removed under any app.

#### conversationHash

* **Type** `ConversationHash | null`

The hash of the group conversation from which a member is being removed. If set to null, it listens for members removed from any group conversation.

#### member

* **Type** `Address | null`

The address of the member being removed from the group conversation. If set to null, it listens for any member being removed.

#### callback

* **Type** `(appId: AppId, conversationHash: ConversationHash, member: Address) => void`

A callback function that will be executed when a member is removed from a group conversation. This callback is passed three arguments:

* `appId`: The App ID under which the group conversation is taking place.
* `conversationHash`: The hash of the group conversation from which the member is being removed.
* `member`: The address of the member being removed.


# Encryptor

Class that provides functionality for public key retrieval and storage, as well as shared secret key computation using the Encryptor extension.

### Usage

Below is a minimal example of how to initialize \`Encryptor:

```ts
import { Encryptor } from '@4thtech-sdk/ethereum';

const encryptor = new Encryptor({
  encryptorExtension,
  walletClient,
});
```

### Parameters

#### config

* **Type** `EncryptorConfig`

The configuration object required to initialize the encryptor service.

#### config.encryptorExtension

* **Type** `EncryptorExtension`

An instance of the Encryptor Extension to be used by the Encryptor.

You can use:

* [EncryptorExtensionConnector](https://github.com/4thtech/wiki.4thtech.io/blob/main/docs/sdk/encryptor/README.md)

#### config.walletClient

* **Type** `WalletClient`

An instance of the wallet client that takes care of sending Ethereum transactions.


# isUserAddressInitialized

Checks if the user address has an associated public key.

### Usage

```ts
const user = '0x...';
const hasPublicKey = await encryptor.isUserAddressInitialized(user);
```

### Returns

`Promise<boolean>`

A promise that resolves to true if the user address has an associated public key, otherwise false.

### Parameters

#### address

* **Type** `Address`

The user's address for which the public key association is being checked.


# retrieveUserPublicKey

Retrieves the public key associated with the given user address.

### Usage

```ts
const user = '0x...';
const publicKey = await encryptor.retrieveUserPublicKey(user);
```

### Returns

`Promise<string | undefined>`

A promise that resolves to the public key associated with the given user address. If the public key is not found, it resolves to undefined.

### Parameters

#### address

* **Type** `Address`

The user's address for which the associated public key is being retrieved.


# storePublicKey

Stores the user's public key.

### Usage

```ts
const txResponse = await encryptor.storePublicKey();
```

### Returns

`Promise<EthereumTransactionResponse>`

A promise that resolves to the response from the `sendTransaction` method on the `walletClient` provided by the developer on `Mail` initialization.


# getState

Retrieves the state of the Encryptor extension.

### Usage

```ts
const encryptorState = await encryptor.getState();
```

### Returns

`Promise<EncryptorState>`

A promise that resolves to the current state of the Encryptor extension.


# getPublicKey

Retrieves the user's public key from the Encryptor extension.

### Usage

```ts
const publicKey = await encryptor.getPublicKey();
```

### Returns

`Promise<string | undefined>`

A promise that resolves to the user's public key or undefined if not found.


# getPublicKeyType

Retrieves the type of the user's public key.

### Usage

```ts
const publicKeyType = encryptor.getPublicKeyType();
```

### Returns

`Promise<string>`

The type of the user's public key.


# computeSharedSecretKey

Computes a shared secret key with the provided public key.

### Usage

```ts
const userPublicKey = '0x...';
const sharedSecretKey = await encryptor.computeSharedSecretKey(userPublicKey);
```

### Returns

`Promise<string | undefined>`

A promise that resolves to the computed shared secret key or undefined if the computation failed.

### Parameters

#### publicKey

* **Type** `string`

The public key with which the shared secret key is computed.


# Encryption

Documentation for the @4thtech-sdk/encryption package

This package allows for easy data encryption and decryption using various encryption methods, ensuring secure data handling within the 4thTech protocol.

### Installation

```bash
npm install @4thtech-sdk/encryption
```

### Core Functionality

#### Encryption Handler

It manages different encryption methods and allows data to be encrypted and decrypted using the specified encryption type. All encryption implementations are managed through this handler.

* Documentation: [Encryption Handler Details](https://github.com/4thtech/wiki.4thtech.io/blob/main/docs/sdk/encryption/encryption-handler/README.md)

#### Encryption Implementations

Different encryption algorithms can be integrated into the 4thTech protocol system by providing custom implementations of the `Encryption` interface.

* [AES Encryption](https://github.com/4thtech/wiki.4thtech.io/blob/main/docs/sdk/encryption/encryption-implementations/aes-encryption/README.md) A symmetric encryption algorithm that offers data encryption and decryption using the Advanced Encryption Standard.
* [Encryptor AES Encryption](https://github.com/4thtech/wiki.4thtech.io/blob/main/docs/sdk/encryption/encryption-implementations/encryptor-aes-encryption/README.md) An extended encryption mechanism that combines AES with the Encryptor extension, enabling shared secret-based encryption between two parties.


# EncryptionHandler

Class responsible for handling different encryption implementations. It provides functionalities to encrypt and decrypt data based on the specified encryption type, allowing you to manage and use multiple encryption algorithms seamlessly.

### Usage

Below is a minimal example of how to initialize EncryptionHandler.

```ts
import { EncryptionHandler } from '@4thtech-sdk/encryption';

const encryptionHandler = new EncryptionHandler({
  encryptionImplementations: [
    /* array of encryption implementations */
  ],
});
```

### Parameters

#### config

* **Type** `EncryptionHandlerConfig`

The configuration object required to initialize the EncryptionHandler.

#### config.encryptionImplementations

* **Type** `Encryption[]`

An array of encryption implementations. Each implementation provides the necessary methods to encrypt and decrypt data.


# addEncryptionInstance

Adds an encryption implementation to the EncryptionHandler.

### Usage

```ts
encryptionHandler.addEncryptionInstance(encryptionImpl);
```

### Returns

`void`

This method does not return a value. Instead, it updates the internal state of the EncryptionHandler by adding the provided encryption instance.

### Parameters

#### encryptionInstance

* **Type** `Encryption`

The encryption implementation that provides the necessary methods to encrypt and decrypt data.


# encrypt

Encrypts the provided data using a specific encryption type.

### Usage

```ts
import { EncryptionType } from '@4thtech-sdk/types';

const dataToEncrypt = new ArrayBuffer(8);
const encryptedData = await encryptionHandler.encrypt(dataToEncrypt, EncryptionType.AES);
```

### Returns

`Promise<ArrayBuffer>`

A promise that resolves with the encrypted version of the provided data, securely transformed using the specified encryption type.

### Parameters

#### data

* **Type** `ArrayBuffer`

The raw data that you want to encrypt. It can be of any content type, as long as it's in the ArrayBuffer format.

#### encryptionType

* **Type** `EncryptionType`

The type of encryption you want to use to secure the data. It should be one of the encryption types supported by the EncryptionHandler.


# decrypt

Decrypts the provided encrypted data using the associated encryption metadata.

### Usage

```ts
import { EncryptionMetaData, EncryptionType } from '@4thtech-sdk/types';

const encryptedData = new ArrayBuffer(8);
const metadata: EncryptionMetaData = {
  type: '4th-tech-aes-gcm',
};
const decryptedData = await encryptionHandler.decrypt(encryptedData, metadata);
```

### Returns

`Promise<ArrayBuffer>`

A promise that resolves with the decrypted version of the provided encrypted data. The decrypted data will match the original content before it was encrypted, and it will be in the ArrayBuffer format.

### Parameters

#### data

* **Type** `ArrayBuffer`

The encrypted data that you want to decrypt. This data should have been encrypted using one of the encryption types supported by the EncryptionHandler.

#### encryptionMetaData

* **Type** `EncryptionMetaData`

The metadata associated with the encrypted data. This metadata provides details about how the data was encrypted, and is crucial for successfully decrypting it.

You can access metadata using the `getMetadata()` method on encryption instance.


# getEncryption

Retrieves a specific encryption implementation from the handler based on the encryption type provided.

### Usage

```ts
import { EncryptionType } from '@4thtech-sdk/types';

const encryptionInstance = encryptionHandler.getEncryption(EncryptionType.AES);
```

### Returns

`Encryption`

The corresponding encryption implementation for the specified type. If the type is found within the handler's internal map, the related encryption instance will be returned.

### Parameters

#### encryptionType

* **Type** `EncryptionType`

The specific type of encryption you want to retrieve. This should correspond to one of the encryption types managed by the EncryptionHandler.


# AES Encryption

`AesEncryption` is an implementation of the `Encryption` interface, offering Advanced Encryption Standard (AES) encryption and decryption services. It uses the Galois/Counter Mode (GCM) of operation which is suitable for encrypting individual files or strings of data.

### Setup

For proper functioning, an AES secret key needs to be either generated or imported into the `AesEncryption` class. Once set up, you can utilize the class methods to encrypt and decrypt data using the AES-GCM mechanism.

Note: If you're integrating `AesEncryption` with `EncryptionHandler`, ensure that the secret key is either generated or imported in the `AesEncryption` instance beforehand. Otherwise, it won't be possible to encrypt/decrypt data.

### Usage

Below is a demonstration of how to use the `AesEncryption` class.

```ts
import { AesEncryption } from '@4thtech-sdk/encryption';
import { arrayBufferToString, stringToArrayBuffer } from '@4thtech-sdk/utils';

// Create an instance of AesEncryption
const aesEncryption = new AesEncryption();

// Generate a secret key
await aesEncryption.generateSecretKey();

// Export the generated secret key
const exportedSecretKeyHex = await aesEncryption.exportSecretKey();

// Or import an existing secret key
// const secretKeyHex = 'YOUR_SECRET_KEY_IN_HEX';
// await aesEncryption.importSecretKey(secretKeyHex);

// Or use the static method to create an AesEncryption instance from a secret key
// const aesEncryption = await AesEncryption.fromSecretKey(secretKeyHex);

// Encrypt data
const plainData = stringToArrayBuffer('Your data to be encrypted');
const encryptedData = await aesEncryption.encrypt(plainData);

// Decrypt data
const decryptedDataBuffer = await aesEncryption.decrypt(encryptedData);
const decryptedData = arrayBufferToString(decryptedDataBuffer);
```


# Encryptor AES Encryption

`EncryptorAesEncryption` is an implementation of the `Encryption` interface that uses AES encryption alongside the Encryptor extension to compute shared secrets. This approach allows data encryption between two parties, ensuring both sender and receiver can decrypt the data.

### Setup

To use \`EncryptorAesEncryption, you need to initialize it with the receiver's address. The class will retrieve the receiver's public key and compute the shared secret. This shared secret is then used to encrypt and decrypt data with AES encryption.

Note: It's crucial to ensure that the receiver's public key is retrievable. If it's not, encryption won't be possible.

### Usage

Below is a demonstration of how to use the `EncryptorAesEncryption` class.

```ts
import { EncryptorAesEncryption } from '@4thtech-sdk/encryption';
import { Encryptor } from '@4thtech-sdk/ethereum';
import { arrayBufferToString, stringToArrayBuffer } from '@4thtech-sdk/utils';

// Create an instance of EncryptorService implementation
const encryptor = new Encryptor({
  /* ... */
});

// Initialize EncryptorAesEncryption with the service
const encryptorAesEncryption = new EncryptorAesEncryption(encryptor);

// Set up with the receiver's address
const receiverAddress = '0x...';
await encryptorAesEncryption.initialize(receiverAddress);

// Encrypt data
const plainData = stringToArrayBuffer('Your data to be encrypted');
const encryptedData = await encryptorAesEncryption.encrypt(plainData);

// For decryption, you also need encryption metadata
const encryptionMetaData = {
  type: EncryptionType.ENCRYPTOR_AES,
  senderPublicKey: 'SENDER_PUBLIC_KEY',
  receiverPublicKey: 'RECEIVER_PUBLIC_KEY',
};
const decryptedDataBuffer = await encryptorAesEncryption.decrypt(encryptedData, encryptionMetaData);
const decryptedData = arrayBufferToString(decryptedDataBuffer);
```


# Encryptor

Documentation for the @4thtech-sdk/encryptor package

This package handles the connection with [Encryptor Extension](https://chrome.google.com/webstore/detail/encryptor/feolajpinjjfikmmeknkdjbllbppojij).

`EncryptorExtensionConnector` is an integral part of this package, which serves as the primary interface between your application and the Encryptor Extension, facilitating operations such as public key retrieval, computation of shared secret key, and checking the state of the extension.

### Installation

```bash
npm install @4thtech-sdk/encryptor
```

### EncryptorExtensionConnector

#### Description

The `EncryptorExtensionConnector` provides methods to interact seamlessly with the Encryptor Extension. It acts as a bridge, ensuring smooth communication, and providing higher-level functions that abstract away the complexity of dealing directly with the extension's APIs.

#### Usage

To use the `EncryptorExtensionConnector`, first import it and create an instance.

```ts
import { EncryptorExtensionConnector } from '@4thtech-sdk/encryptor';

const encryptorExtension = new EncryptorExtensionConnector();
```

Once instantiated, you can use various methods like `isInstalled()`, `getPublicKey()`, and others to interact with the Encryptor Extension.


# isInstalled

Determines if the Encryptor Extension is installed.

### Usage

```ts
const isInstalled = await encryptorExtension.isInstalled();
```

### Returns

`Promise<boolean>`

A promise that resolves to true if the Encryptor Extension is installed, otherwise false.


# isInitialized

Checks if the Encryptor Extension is initialized. Initialized means that the extension has generated keypair.

### Usage

```ts
const isInitialized = await encryptorExtension.isInitialized();
```

### Returns

`Promise<boolean>`

A promise that resolves to true if the Encryptor Extension is initialized, otherwise false.


# isLocked

Determines if the Encryptor Extension is locked.

### Usage

```ts
const isLocked = await encryptorExtension.isLocked();
```

### Returns

`Promise<boolean>`

A promise that resolves to true if the Encryptor Extension is locked, otherwise false.


# isUnlocked

Determines if the Encryptor Extension is unlocked.

### Usage

```ts
const isUnlocked = await encryptorExtension.isUnlocked();
```

### Returns

`Promise<boolean>`

A promise that resolves to true if the Encryptor Extension is unlocked, otherwise false.


# getState

Retrieves the current state of the Encryptor Extension.

### Usage

```ts
const currentState = await encryptorExtension.getState();
```

### Returns

`Promise<EncryptorState>`

A promise that resolves to the current state of the Encryptor Extension.


# getPublicKey

Retrieves the public key from the Encryptor Extension.

### Usage

```ts
const publicKey = await encryptorExtension.getPublicKey();
```

### Returns

`Promise<string | undefined>`

A promise that resolves to the public key retrieved from the Encryptor Extension or undefined if the public key is not available.


# getPublicKeyType

Gets the type of the public key used by the Encryptor Extension. This method returns a unique type identifier for the public key. It's important to ensure uniqueness when developing custom extensions.

### Usage

```ts
const publicKeyType = encryptorExtension.getPublicKeyType();
```

### Returns

`Promise<string>`

The unique public key type identifier. In this implementation, it returns `'BL_ENCRYPTOR_EC'`.

**Note:** If you're developing your own extension, make sure the returned type identifier is unique to your implementation. This ensures no conflicts arise with other extensions.


# computeSharedSecretKey

Computes a shared secret key using a provided public key. This method is useful for creating a common secret between parties, which can be used for tasks like symmetric encryption.

### Usage

```ts
const userPublicKey = '0x...';
const sharedSecretKey = await encryptorExtension.computeSharedSecretKey(userPublicKey);
```

### Returns

`Promise<string | undefined>`

A promise that resolves to the computed shared secret key or undefined if the computation failed.

### Parameters

#### publicKey

* **Type** `string`

The public key with which the shared secret key is computed.


# Storage

Documentation for the @4thtech-sdk/storage package

This package is designed to optimize storing and retrieving procedures, enhancing data management within the 4thTech protocol system.

### Installation

```bash
npm install @4thtech-sdk/storage
```

### Core Functionality

#### Remote Storage Provider

The heart of the storage system is the **Remote Storage Provider**. It's an abstract class that outlines the fundamental operations for any storage provider. All custom storage provider implementations will extend this class to leverage its capabilities.

* Documentation: [Remote Storage Provider Details](https://github.com/4thtech/wiki.4thtech.io/blob/main/docs/sdk/storage/remote-storage-provider/README.md)

#### Remote Storage Provider Implementations

Different storage solutions can be integrated into the 4thTech protocol system by creating custom implementations of the `RemoteStorageProvider` abstract class.

* [PollinationX Storage Provider](https://github.com/4thtech/wiki.4thtech.io/blob/main/docs/sdk/storage/remote-storage-providers/pollination-x/README.md) A provider tailored for the BitTorrent File System (BTFS). It offers seamless upload and download functionalities for files on BTFS.


# Remote Storage Provider

A Remote Storage Provider is an abstract class representing a provider for remote storage functionalities. This class is intended to be extended by a specific implementation of a remote storage provider. It offers methods to upload and download files, as well as the ability to monitor upload progress.

### Usage

Below is a demonstration of extending the `RemoteStorageProvider` class for a custom implementation. You'll need to provide the actual logic for the `upload` and `download` methods based on your specific remote storage solution.

```ts
import type { FileInput } from '@4thtech-sdk/types';
import { RemoteStorageProvider } from '@4thtech-sdk/storage';

class MyRemoteStorageProvider extends RemoteStorageProvider {
  public async upload(file: FileInput, fileName: string): Promise<string> {
    // TODO: Implement the logic to upload the file to your storage.

    // Emitting the upload progress (for demonstration, assuming 100% here).
    this.emitUploadProgress(100, fileName);

    // Replace with the actual uploaded file URL.
    const uploadedFileUrl = 'https://your-storage.com/path-to-uploaded-file';
    return uploadedFileUrl;
  }

  public async download(url: string): Promise<ArrayBuffer> {
    // TODO: Implement the logic to download the file from your storage.

    // Replace with the actual file content.
    const fileContent = new ArrayBuffer(0);
    return fileContent;
  }
}
```


# upload

Upload a file to a remote storage provider.

### Usage

```ts
const uploadedFileUrl = await myRemoteStorage.upload(file, fileName);
```

### Returns

`Promise<string>`

A promise that resolves to the URL of the uploaded file.

### Parameters

#### file

* **Type** `FileInput`

The file data that you want to upload.

#### fileName (Optional)

* **Type** `string`

The name you want to give to the uploaded file.


# download

Download a file from a remote storage provider.

### Usage

```ts
const fileContent = await myRemoteStorage.download(url);
```

### Returns

`Promise<ArrayBuffer>`

A promise that resolves to the content of the downloaded file as an ArrayBuffer.

### Parameters

#### url

* **Type** `string`

The URL of the file you want to download.


# onUploadProgress

Set a listener for upload progress.

### Usage

```ts
myRemoteStorage.onUploadProgress((percent, fileName) => {
  console.log(`Upload Progress (${fileName}): ${percent}%`);
});
```

### Returns

`void`

This method does not return any value.

### Parameters

#### listener

* **Type** `UploadProgressCallback`

A callback function to receive updates on the upload progress.


# offUploadProgress

Remove the upload progress listener.

### Usage

```ts
myRemoteStorage.offUploadProgress();
```

### Returns

`void`

This method does not return any value.


# emitUploadProgress

Emit an upload progress event. This is typically used internally, but can be useful if you want to manually trigger an upload progress update.

### Usage

```ts
myRemoteStorage.emitUploadProgress(percent, fileName);
```

### Returns

`void`

This method does not return any value.

### Parameters

#### percent

* **Type** `number`

The progress percentage (0-100) of the upload.

#### fileName (Optional)

* **Type** `string`

The name of the file currently being uploaded.


# PollinationX Storage Provider

`PollinationX` is an implementation of the `RemoteStorageProvider` abstract class that facilitates interaction with the BitTorrent File System (BTFS) for remote storage purposes. With the methods it provides, you can upload and download files on BTFS.

### Setup

Before using the `PollinationX` storage provider, ensure you've properly set it up by providing the **base URL** and a valid **authorization token**.

### Usage

Below is a demonstration of how to use the \`PollinationX class. You can use this provider directly without needing any custom implementation.

```ts
import { PollinationX } from '@4thtech-sdk/storage';

const baseURL = 'https://your-pollination-x-gateway-url.com';
const token = 'YOUR_POLLINATION_X_TOKEN';

// Create an instance of PollinationX
const pollinationX = new PollinationX(baseURL, token);

// To upload a file
const uploadedFileUrl = await pollinationX.upload(file, fileName);

// To download a file
const fileContent = await pollinationX.download(uploadedFileUrl);
```

### Links

* <https://wiki.pollinationx.io/>


# Types

Documentation for the @4thtech-sdk/types package

This package contains the type declarations used across all the other packages.

### Installation

```bash
npm install @4thtech-sdk/types
```

***

Coming soon...


