# NuLink Introduction

NuLink, as a Web3-based ZK Provable Data Privacy Solution for DApps(Decentralized Applications), is revolutionizing the landscape of Dapps. This cutting-edge platform empowers application developers with a comprehensive suite of security and privacy features, meticulously designed to adhere to industry best practices.

The NuLink technology platform is a fusion of a robust blockchain foundation, access control mechanisms (Proxy Re-Encryption, Attribute-Based Encryption), and secure computation protocols (Zero-Knowledge Proof, Secure Multi-party Computation, Fully Homomorphic Encryption). This technical foundation establishes NuLink as an integral and indispensable solution for data sharing and computation services, particularly tailored for the realm of preserving data privacy.

## Solution

### Data Availability

At our core, we are committed to safeguarding data privacy. One of our primary objectives is to address the issue of data availability, which is typically divided into two parts. Firstly, we strive to provide consumers with the means to ascertain that the seller has the required data before making a request. Secondly, we aim to establish a mechanism for verifying the authenticity of the data in its encrypted form.

Within the NuLink network, Zero-Knowledge Proof is used to ensure that all functional nodes, including storage nodes, computing nodes, and proxy nodes, conduct publicly verifiable data processing and computing operations. At the same time, prior to authorizing data access, the data owner is required to present a Zero-Knowledge Proof. This proof verifies that the encrypted data is aligned with its plaintext counterpart, irrespective of the encryption scheme being used. This approach endows NuLink network with enhanced flexibility.

### Data Sharing

An additional challenge we need to address is how to maintain data security during transmission to other parties. Specifically, we must ensure that data remains uncompromised during transmission, and that it is only accessible to authorized individuals approved by the data owner.

NuLink addresses this challenge by leveraging proxy re-encryption, identity-based encryption, and attribute-based encryption. Initially, data is encrypted at the user-end, and access to the data is granted to authorized parties using the PRE, IBE, or ABE algorithms. Receivers can then decrypt the data using their private key as appropriate. Throughout this process, only the data owner and authorized parties can access the original data, ensuring its confidentiality and security.

### Data Computing

The last issue we are trying to address is privacy concerns related to data computation. In certain scenarios involving edge computing or machine learning, the individual who owns the data may only wish to grant access for computing purposes on a specific model. As a result, the authorized party would only receive the computed result and not the original dataset.&#x20;

NuLink will utilize FHE technology to enable privacy-preserving data computation. This approach leverages the unique property of Fully Homomorphic Encryption, which enables calculations to be performed on ciphertext. Initially, the dataset will be encrypted and transmitted to the computing providers. The computing providers will then execute the desired computation, such as a prediction model for machine learning. Ultimately, the encrypted result will be returned to the authorized party for decryption.

## Architecture

The NuLink network integrates the Application Layer, the Cryptography Layer, the Storage Layer, the Blockchain Layer and the Watcher Network.

![Architecture of the NuLink network](/files/lSLC2DMMMAi2h8m4cax4)

1. The Application Layer: The Application Layer acts as an interface between the system and the application, facilitating direct communication with the application while also liaising with the Cryptography Layer to validate access to the application's confidential information.
2. The Cryptograph Layer: The Cryptography Layer carries out cryptographic functions for the Application Layer, such as generating keys, encrypting, decrypting, and other related tasks. It also connects to the Storage Layer to facilitate the uploading and downloading of encrypted privacy data.
3. The Storage Layer: Our platform's Storage Layer is a secure network created for the purpose of storing confidential data in encrypted form. At present, we utilize IPFS (InterPlanetary File System) as the primary decentralized storage network. Nonetheless, we intend to incorporate additional storage networks like S3 in the coming times.
4. The Blockchain Layer: The Blockchain Layer is responsible for managing staking node registration and service requests within the blockchain system. As of now, only Ethereum is supported for staking node registration. Nevertheless, users can still make service requests in other blockchain systems, such as Binance Smart Chain, Polygon, Polkadot, Arbitrum, Aptos or Sui.
5. The Watcher Network: The Watcher Network is a relayer network that transfers staking node information from Ethereum to other blockchain systems. To ensure its decentralization and security, the Watcher Network is maintained under an on-chain governance mechanism (DAO).


# Roadmap

## 2021 - Q1

1. **Project Start:**
   * Initiate the NuLink project.

## 2021 - Q4

1. **Deliver NuLink Polkadot Pallet and Launch Polkadot Watcher Node:**
   * Complete the development of the NuLink Polkadot pallet and deploy the Polkadot watcher node.

## 2022 - Q2

1. **NuLink Core Library v.1 Release:**
   * Deploy Watch Network functionality.
   * Fully support Proxy Re-Encryption (PRE).
2. **Release NuLink Agent Plugin and NuLink Data Sharing Frontend:**
   * Introduce the NuLink Agent plugin and frontend for seamless data sharing.

## 2022 - Q4

1. **Launch NuLink’s Testnet Horus 1.0 in BNB Smart Chain:**
   * Release NuLink worker node installer.
   * Introduce NuLink staking Dapp.
   * Deploy NuLink Agent.
   * Launch NuLink File Sharing Dapp.

## 2023 - Q2

1. **NuLink Core Library v.2 Release:**
   * Deploy the Storage Layer to support additional decentralized storage solutions.
2. **NuLink API Library Release:**
   * Release NuLink Agent.
   * Launch NuLink SDK.

## 2023 - Q4

1. **Launch NuLink’s Testnet Horus 2.0:**
   * Introduce the NuLink Dashboard.
   * Release the NuLink Worker Node Package.
   * Support the NuLink Token Incentive Mechanism.

## 2024 - Q1

1. **Update NuLink’s Testnet Horus 2.0:**
   * Release NuLink Snaps.
   * Launch NuLink Web Agent.
   * Deploy NuLink Ecosystem Dapps.
   * Support Third-party Storage Network.
   * Implement Blockchain Interoperability Mechanism.

## 2024 - Q2

1. **NuLink Mainnet Launch:**
   * Transplant all modules from the testnet to the mainnet.
   * Activate On-chain Governance (DAO).
2. **Zero-Knowledge Proof (ZKP) System Integration:**
   * Integrate the ZKP system into the mainnet.

## 2024 - Q4

1. **Update NuLink’s Testnet Horus 3.0:**
   * Release NuLink Staking.
   * Release NuLink Auction.
   * Release NuLink Bridge.
   * Deploy NuLink Ecosystem Dapp"CreamStream".

## 2025 - Q4

1. **Fully Homomorphic Encryption (FHE) Integration:**
   * Integrate the FHE algorithm into the mainnet.


# Proxy Re-encryption

Proxy re-encryption (PRE) is a type of public-key encryption (PKE) that allows a proxy entity to transform or re-encrypt data from one public key to another, without having access to the underlying plain text or private keys. The proxy re-encryption operation process is as follows:

![Proxy Re-encryption operation process](/files/6lTYawXgNJw6jDiQCdnM)

1. Publisher Alice encrypts the data m with her own public key into cA, then Alice sends the ciphertext cA to the proxy and generates a re-encryption key for her, which is calculated by Alice herself.
2. Next, the proxy uses the re-encryption key to convert the ciphertext cA into a ciphertext cB that can be decrypted by Bob with his secret key and sends it to Bob. The proxy only provides computing conversion services and cannot get plaintext.
3. Bob decrypts the plaintext m that Alice wants to share securely.

Proxy re-encryption plays a role in private data sharing in NuLink. Specifically, NuLink uses the Umbral Proxy Re-Encryption Scheme. Umbral is a threshold Proxy Re-Encryption scheme following a Key Encapsulation Mechanism (KEM) approach. It is inspired by ECIES KEM, and the BBS98 proxy re-encryption scheme. With Umbral, Alice – the generic name for data owners in NuLink KMS (Key Management System) – can delegate decryption rights to Bob for any ciphertext intended to her through a re-encryption process performed by a set of N semi-trusted proxies. When at least t of these proxies (out of N) participate by performing re-encryption, Bob is able to combine these independent re-encryptions and decrypt the original message using his private key.&#x20;

Using Umbral, NuLink can not only easily realize single-user to single-user private data sharing – we emphasize again that Umbral is a threshold scheme – NuLink can also realize single-user to multi-user private data sharing.


# Identity-Based Encryption & Attribute-Based Encryption

Both identity-based encryption (IBE) and attribute-based encryption (ABE) are public key encryption schemes that control access rights. The former can specify the identity information of the recipient, while the latter can specify the attributes of the receiver. NuLink uses these two technologies to achieve more functional data sharing.&#x20;

Using public key encryption to transmit data has certain shortcomings and risks. For example, the public key is generally a series of meaningless random numbers. If the public key is used incorrectly in the encryption process, the ciphertext cannot be decrypted by the correct receiver. At the same time, it is likely to be disclose the information to the wrong user, or even to malicious users. In fact, in real life, there is such an attack method: malicious users deceive the sender and replace the receiver’s public key.&#x20;

IBE solves this problem by binding the user’s identity information directly to the public key. It is similar to an ideal email system: If you know someone’s identity, you can send them a letter that only they can read. You can authenticate their signature.

![IBE and ABE example usage](/files/XzPaDxA4TGhBEYLlHNSq)

On this basis, ABE has made a further functional expansion. If we define attributes as the characteristics of things or information, policy is the relationship between these features. Then IBE uses the simplest policy and attribute matching, that is, authenticating identity attributes. In ABE, there are more diverse choices of attributes and policies. ABE is generally divided into two categories. KP-ABE (key policy) embeds the policy into the key and the attribute into the ciphertext. CP-ABE (ciphertext policy) embeds the policy into the ciphertext and the attribute into the key. These two schemes have a dual relationship in structure, so analogy transfer is often carried out in the scheme design, but they are very different in their specific application scenarios.

NuLink chooses CP-ABE, because the policy is embedded in the ciphertext. This means that the data owner can decide which attributes can access the ciphertext by setting the policy, which is equivalent to making an encrypted access control for this data whose granularity can be refined to the attribute level.


# Zero-Knowledge Proof

Zero-Knowledge Proof (ZKP) means that the prover makes the verifier believe that a certain conclusion is correct without providing any useful information to the verifier. Zero-Knowledge Proof was first proposed by S Goldwasser et al in 1989. It has the following three properties:

* Completeness: If both the prover and the verifier party are honest and follow every step of the proof process, then the proof must be successful and the verifier must accept the prover.
* Soundness: No one can forge a new proof and successfully make it pass verification.
* Zero Knowledge: After the verification process, the verifier verifies that the prover has the knowledge but does not get any information about that knowledge. From the point of view of the prover, they did not breach privacy.

![Zero-Knowledge Proof (ZKP)](/files/KcMq54Fys3zwP4lS5OA7)

By whether the participants need to interact or not, Zero-Knowledge Proof can be divided into Interactive Zero-Knowledge Proof and Non-Interactive Zero-Knowledge Proof or NIZK. NIZK is suitable for decentralized scenarios. The commonly used NIZK schemes are zk-SNARK, zk-STARK, Bulletproofs, PLONK, Supersonic, Malin and so on. Each scheme has its own advantages and we can choose the appropriate one depending on the different scenarios involved.

ZKP provides an additional layer of security and privacy for users by providing publicly verifiable proof, making sure that users of the NuLink network can easily verify that their data is being correctly stored and processed


# Fully Homomorphic Encryption

Fully homomorphic encryption (FHE) refers to the ability to calculate ciphertext without the private key. That is to say, for any valid f and plaintext m, there is a special property f(Enc(m)) = Enc(f(m)).

![Fully Homomorphic Encryption (FHE)](/files/DEk8q5b266WVZYmUG3zX)

FHE is known as the holy grail of cryptography. This problem was proposed by Rivest in 1978. Thirty-odd years later, in 2009, Craig Gentry constructed the first FHE scheme.

At present, secure and efficient FHE schemes are based on the LWE problem and Ring-LWE problem on lattice. They are anti-quantum and can provide sufficient security even in the post-quantum era.&#x20;

Fully Homomorphic Encryption is restricted by efficiency, which mainly depends on the operation mode of ciphertext. While FHEW and TFHE cryptosystems are more suitable for dealing with boolean logic operations, BGV, BFV and CKKS are more suitable for batching and calculating affine transformations. For nonlinear arbitrary functions, the latest PBS technology has a good efficiency performance. Therefore, NuLink will build different FHE algorithms to improve efficiency.&#x20;

Fully Homomorphic Encryption has a wide range of theoretical and practical applications, especially in decentralized privacy-preserving products.&#x20;

Nodes in the system whose computing power is not strong enough can store their data in the Storage Layer in the form of ciphertext. When data computing is needed, the user initiates computing authorization to the computation nodes. The computation nodes carry on the corresponding ciphertext operation to get the encrypted result, the user downloads the result and decrypts it, and then the final plaintext result can be obtained. In the whole process of computing, only the owner of the data has the ability to decrypt, so users can be guaranteed data privacy.&#x20;

We need to emphasize that this can be used as a component of multi-party secure computing, rather than just completing the proxy computation of two parties.


# Introduction

NuLink's product offerings are designed to meet the specific requirements of both the supply and demand sides in the decentralized ecosystem. The platform comprises tools and solutions tailored for stakers, DApp builders, and DApp users, ensuring a comprehensive and inclusive approach to data privacy and management.

## Supply Side

The supply side in NuLink refers to stakers—individuals who stake their NLK token and provide services in the NuLink network. In NuLink, there are four types of stakers: proxy workers, computation nodes, storage providers, and watchers. Currently, only proxy workers are online.

Stakers initiate their participation by depositing NLK tokens using the NuLink Staking Dashboard. Subsequently, they install and start running the corresponding service node installer (e.g., proxy workers use the NuLink Worker Installer). Once the NuLink worker node is successfully running, stakers bond the node to their staking account through the NuLink Staking Dashboard to start receiving rewards.

### For Stakers

[**Stakers**](/products/stakers) are essential contributors to the NuLink network, providing valuable services and earning rewards. NuLink offers dedicated tools for stakers:

* [**NuLink Staking Dashboard:**](broken://pages/gIAKEN5w6zOJLsfWYa9G) A user-friendly interface empowering stakers to efficiently manage staking activities. It allows them to stake token, bond node, monitor contributions, track rewards, and ensure the smooth operation of NuLink services.
* [**NuLink Worker Node Installer:**](/products/stakers/nulink_worker) The NuLink Worker Node Installer simplifies the deployment of NuLink worker nodes.

## Demand Side

The demand side in NuLink involves users who pay NLK to obtain services from the supply side. The products for the demand side are categorized into two types: those for DApp builders (NuLink Agent SDK and NuLink SDK) and those for DApp users (NuLink Agent and NuLink Snaps). The relationships between these components and layers are visualized in a diagram, highlighting the interconnectedness and collaborative nature required for the successful operation of the NuLink network.

![Operation Flow](/files/4fELvscJ2LzHDfot5k2F)

### For DApp Builders

[**DApp builders**](/products/dapp_builders) play a crucial role in integrating NuLink's data privacy services into their products. NuLink provides two powerful SDKs to facilitate seamless integration:

* [**NuLink Agent SDK:**](/products/dapp_builders/agent_sdk)The NuLink Agent SDK equips developers with essential software development tools and resources. It empowers them to seamlessly integrate NuLink Agent functionality into their applications. This SDK enables secure and efficient communication between DApps and the NuLink network.
* [**NuLink SDK:**](/products/dapp_builders/agent_sdk)The NuLink SDK is a robust and comprehensive software development kit designed to provide developers with extensive capabilities. It facilitates flexible connections with the NuLink network, enabling advanced cryptographic operations and seamless interaction. Developers can leverage the NuLink SDK to unlock the full potential of the NuLink ecosystem, ensuring enhanced security and privacy for their applications.

### For DApp Users

[**DApp users**](/products/dapp_users) benefit from NuLink's data privacy-focused solutions once DApps are connected to the NuLink network using SDKs. Users can interact with NuLink Agent or Snaps in DApp to manage their privacy data using private keys:

* [**NuLink Agent:**](/products/dapp_users/nulink_agent) NuLink Agent is a web-based digital wallet that facilitates seamless communication and interaction between the NuLink network and applications. It acts as an intermediary, relaying requests and responses between applications and the underlying layers of the NuLink network.
* [**NuLink Snaps(Coming soon):**](/products/dapp_users/nulink_snaps) NuLink Snaps serves as a decentralized end-to-end data management tool designed for Web3 Dapps, providing users with a unique perspective on data privacy and access control. Operating as a specialized iteration of MetaMask Snaps, NuLink Snaps leverages the private key stored in MetaMask to efficiently manage digital assets and privacy data. This bespoke solution grants Dapp users intricate control over the access rights to their private data. With NuLink Snaps' tailored features, users can confidently store and share their data while maintaining control, eliminating the need to delegate authority to Dapp Admins.
* [**Demostration Dapp:**](/products/dapp_users/agent_usecase) The "File Transfer" Dapp serves as a third-party example, demonstrating the use of the NuLink Agent SDK to interact with the NuLink Agent. This showcase underscores the effortless integration and functionality made possible by the NuLink Application Layer, empowering developers to harness the capabilities of the NuLink network for secure file transfers and data sharing.

## Horus3.0 Testnet

[**Horus3.0**](/products/testnet) Network stands as NuLink's dedicated testnet, offering developers and community members an environment to experiment with and implement proprietary security infrastructure components into their Web3 applications. This comprehensive testnet integrates all the products from both the supply and demand sides.


# Target Audience and Use Cases

## Target Audience

* **Enterprise Organizations:** Large companies and organizations that deal with sensitive data and have a need for secure and privacy-preserving data sharing. This can include industries such as finance, healthcare, legal, and government.
* **Data Privacy Professionals:** Privacy officers, compliance officers, and data protection professionals who are responsible for ensuring data privacy and regulatory compliance within their organizations.
* **Web3 Developers and Integration Teams:** Software developers and integration teams who are responsible for integrating the privacy data sharing capabilities into existing systems or developing custom applications leveraging the Proxy Re-encryption technology.
* **Cryptography enthusiasts:** Cryptography enthusiasts and researchers exploring advanced privacy technologies.

## Use Cases

* **Secure File Sharing and Collaboration:** The web agent can be used as a secure file sharing solution, enabling teams or individuals to share files securely while maintaining control over access rights and ensuring privacy.
* **Confidential Client Data Sharing:** Industries such as healthcare and finance often need to share confidential client data securely. The web agent facilitates privacy-preserving data sharing, allowing authorized parties such as doctors, insurance providers, or financial institutions to collaborate and access necessary information while protecting sensitive client data.
* **Secure Social Network:** By leveraging Proxy Re-encryption technology, the secure social network provides users with enhanced control over their shared data and fosters a private and trusted environment for Private Messaging, Confidential Group Discussions, Secure File Sharing, Privacy-Preserving User Profiles,Encrypted Posts and Updates, etc.
* **Collaboration Platforms:** Collaboration tools and platforms can integrate the web agent to add an extra layer of privacy and security to shared documents, discussions, or project data.
* **Cloud Storage Security:** The web agent can be used as a privacy layer for cloud storage solutions, ensuring that data stored in the cloud remains encrypted and can only be accessed by authorized users with the proper decryption keys.
* **IoT Data Sharing:** The web agent can be applied in Internet of Things (IoT) environments, allowing secure and private sharing of sensor data between devices, applications, or stakeholders.


# NuLink for Stakers

Stakers are essential contributors to the NuLink network, supporting decentralized infrastructure and providing valuable services. This guide will walk you through the staking process, detail the roles available, and explain the reward and fee structures.

In the NuLink network, there are two types of stakers: grid maintainers and standard stakers.

* **Grid Maintainers:** Grid maintainers operate a grid by running a worker node connected to the network, playing a key role in ensuring stability and maintenance. In return, they earn two types of rewards: a Service Bonus from the network and a delegation fee from standard stakers who delegate their tokens to the grid.
* **Standard Stakers:** Standard stakers do not need to run a node. Instead, they choose a grid to stake with, delegating their tokens to a grid maintainer. In return, they receive rewards from the grid, with a portion allocated to the grid maintainer based on the grid's predefined fee rate.

This guide will help you understand each role and make the most of your staking experience in the NuLink network.

## Staking Dashboard

[NuLink Staking Dashboard](https://dashboard.testnet.nulink.org) is a user-friendly interface designed to empower stakers in managing their staking activities. Key features include:

* **Stake Statistics**: Provides a clear overview of staking metrics and performance.
* **Grid Auction and Management**: Allows users to participate in grid auctions and manage grid settings.
* **Stake Management**: Simplifies the process of staking, unstaking, and tracking rewards.
* **Cross-Chain Bridge**: Facilitates token transfers across different blockchain networks, enhancing flexibility for stakers.

This dashboard streamlines staking and grid management, making it accessible for all types of participants in the NuLink network. Learn more about the [NuLink Staking Dashboard](/products/stakers/dashboardoverall).

## NuLink Worker Installer

The [**NuLink Worker Installer**](/products/stakers/nulink_worker) simplifies the deployment of NuLink worker nodes, enabling stakers to contribute computing resources to the NuLink network efficiently. The installation process involves:

1. [**Creating Worker Account:**](/products/stakers/nulink_worker/eth_account) Stakers need to create a dedicated worker account to manage their worker node.
2. [**Worker Installation:**](/products/stakers/nulink_worker/worker_install) Detailed instructions on installing the NuLink worker on the staker's infrastructure.
3. [**Initialization and Running:**](/products/stakers/nulink_worker/worker_running) Guidance on initializing and running the NuLink worker node for optimal performance.
4. [**Worker Update:**](/products/stakers/nulink_worker/worker_update) Information on updating the NuLink worker to the latest version for access to new features and improvements.

Explore the [NuLink Worker Installer](/products/stakers/nulink_worker) for step-by-step instructions.

**Warning:** Do not use same address for staker account and worker account.


# Staking Dashboard

## NuLink Staking Dashboard

### Overview

The NuLink Staking Dashboard is a comprehensive platform for managing staking-related activities within the NuLink network. Users can log in to their staking accounts through the MetaMask wallet, bid for a grid, manage grid settings, stake NLK tokens to a grid, bond a `Worker` account to a grid for rewards, and more.

You can access the NuLink Staking Dashboard through this [link](https://dashboard.testnet.nulink.org).

Remark: For testnet user, users can obtain the initial funds of NLKs (test) and BNBs (test) by clicking the faucet button located in the upper right corner.

![Faucet](/files/AFbDxtNJKc7hoK1hGPyf)

NuLink Staking dashboard provides users with the flexibility to choose between Dark and Light modes. To switch between these modes simply clicking the button next to the faucet button.

## Getting Started with the Staking Dashboard

The NuLink Staking Dashboard is a powerful tool designed to give stakers comprehensive control and insights into their staking activities on the NuLink network. The dashboard is organized into five main sections, each serving a specific purpose.

![Overall](/files/EC9oftw9K3CJJnX318eT)

### 1. Dashboard

The **Dashboard** page serves as the main hub, providing an overview of key staking information and metrics. Refer [here](/products/stakers/dashboardoverall/dashboard) for detail instruction.

### 2. Staking

The **Staking** page allows users to manage individual staking options and assets, including staking, unstaking, and tracking rewards. Refer [here](/products/stakers/dashboardoverall/staking) for detail instruction.

### 3. Auction

The **Auction** section enables users to participate in grid auctions and submit bids for available grids. Refer [here](/products/stakers/dashboardoverall/auction) for detail instruction.

### 4. My Stake Grids

The **My Stake Grids** area allows users to manage their personal staking grids, including grid configuration and status. Refer [here](/products/stakers/dashboardoverall/grid) for detail instruction.

### 5. Bridge

The **Bridge** tool facilitates token transfers across different blockchain networks, providing flexibility and accessibility for stakers. *This page will be available soon.*


# Dashboard

The dashboard page include two sub-page, staking reward page and service bonus page.

## Staking Reward Statistics

The Staking Reward sub-page is the primary landing page for the NuLink Staking Dashboard, offering a comprehensive overview of staking activities. Data is organized by epochs, and the default view is set to the current Epoch. Users can switch to other epochs by using the dropdown menu.

![Dashboard](/files/oyVTPIaIyXV7mDDY4yTd)

### Staking Amount

The left panel displays the `Staking Amount` information:

* `VALID AMOUNT` shows the total valid staking amount of all stakers in the selected epoch.
* `TOTAL AMOUNT` indicates the total staking amount of all stakers in the selected epoch.

![Staking Amount](/files/CMYdqYJGg7dPSXFFa1kx)

### Staking Reward

The right panel showcases the `Staking Reward` details:

* `CURRENT EPOCH REWARD` represents the staking rewards generated in current epoch.
* `ACCUMULATED REWARD` is the cumulative staking rewards generated across all Epochs.

![Staking Reward](/files/844PfUjS3VnbhKLihwMm)

### Total Staking Grids Count

Further below, there are three boxes displaying:

* `Total Staking Grids` reveals the total number of stake grids in the displayed epoch.
* `Current Epoch` indicates the user selected epoch number.
* `Total Epoch` represents the total count of all epochs.

![Total Staking](/files/z3c3VcAWVNlpfvm3zByV)

### Staking Reward Distribution

The image below demonstrates the Staking Reward Distribution list, presenting comprehensive staking-related information for each user receiving rewards.

![Staking Reward Distribution](/files/bSeC1GDFW1wHC1Qr9dIt)

STAKE: Clicking this takes you to the staking details page, with detailed rules described in the "Staking" section.

* `Stake Grid`: Slot number, used to distinguish between different slots.
* `Current Epoch Fee`: The fee for the current epoch, set in the previous epoch.
* `Next Epoch Fee`: The fee for the next epoch, to be set during the current epoch.
* `Staking Number`: The number of participants in staking.
* `Staking Amount`: The amount of NLK staked.
* `Living ratio`: A metric within the NuLink network that represents the uptime of a node (higher values lead to greater rewards).
* `STAKE`: Clicking this takes you to the staking details page, with detailed rules described in the [Staking](/products/stakers/dashboardoverall/staking) section.

## Service Bonus Statistics

To navigate to the Service Bonus page, simply click the `Service Bonus` button located in the dashboard menu. The displayed data is categorized by batches, with the default view set to the current batch. Users can easily scroll down to explore information from other batches.

![Service Bonus](/files/qbmWTw5VxXEdkiUMHamI)

### Service Bonus

The left panel displays the `Service Bonus` information:

* `CURRENT BATCH BONUS` indicates the bonus amount generated in the user selected batch.
* `CUMULATIVE BATCH BONUS` represents the total bonus amount generated across all batches.

### Batches

The right panel showcases the `Batches` details:

* `CURRENT BATCH` shows the user selected batch number.
* `TOTAL BATCH` represents the total count of all batches.

### Service bonus from each blockchain

The image below presents the service bonus collected from each blockchain.

![Bonus from each chain](/files/P5WsPc5jhpNGAqGk3xZl)

Currently, only BSC is supported, and other chains will gradually become available.

### Service bonus distribution

Scrolling further, you will see the `Service Bonus Distribution` section. Only users who have installed a Stake Grid and bound it to a worker are eligible to receive service bonuses. The distribution of 80% of the service bonus from each batch is based on each user’s Reputation Score Quota (the Reputation Score is related to the uptime of the node—the higher the uptime, the higher the score).

![Bonus from each chain](/files/eLZgyqVRl7L3gp4RrMkm)

### Foundation Distribution

The image below demonstrates the Foundation Distribution, where 15% of the service bonus generated in each Batch is allocated to the NuLink Network Foundation's account.

![Foundation Distribution](/files/1DU4FxfEs70gqaHwBs0V)

### Burning Record

This image illustrates the Burning Record, where 5% of the service bonus from each Batch is burned.

![Burning Record](/files/Aqk3KxFcOMqVxMZHcB0w)


# Staking

After logging in, the left frame is for staking participants. Clicking "STAKE NLK NOW" will return to the "Staking Reward Distribution" page (1 -> 4), where you can select the slot you want to stake in. Click "STAKE" to enter the Manage Staking page.

This page provides access points for two roles: `Stake Participant` and `Grid Manager`. Participation in staking requires users to log in first. Click `Sign In` at the top right, which will prompt the wallet authorization. Here, we will use the Metamask wallet as an example.

![Wallet Connection](/files/KtErnl4DKXuQC4z9GAii)

## Staing NLK & Earn Rewards

After logging in, the left section is for staking participants. Clicking `STAKE NLK NOW` will return to the `Staking Reward Distribution` page, where you can select the slot you want to stake in, Click `STAKE` to enter the `Manage Staking` page.

## Manage Staking

![Manage Staking](/files/2IobzhODN4RU7mhRpTF2)

This page displays detailed information about your staking in the selected slot, including principal, staking rewards, etc. The key difference between `MY STAKING IN POOL` and `PENDING STAKING AMOUNT` is that `MY STAKING IN POOL` represents the amount that has already taken effect during the current epoch, while `PENDING STAKING AMOUNT` represents the amount staked during the current epoch, which will take effect in the next epoch.

### Stake

Click `STAKE` to stake your NLK, as shown below:

![Stake](/files/ENOgcBcJYJpNFIVxR1mK)

You can manually enter the amount you wish to stake or click `MAX` to input your entire balance. After confirming the amount, click `STAKE`, which will trigger a pop-up to confirm the staking details, including the start of interest accrual and the time of withdrawal. Click `YES, I’M SURE` to trigger the wallet for gas fee payment. Once paid, the staking is successful.

### Unstake

There are two types of unstaking: `UNSTAKE AMOUNT FROM POOL` and `UNSTAKE`, as shown below:

![Unstake](/files/rsVrzk2jmstaj1ukVwGC)

* `UNSTAKE AMOUNT FROM POOL` will allow you to withdraw your principal after the current epoch ends.
* `UNSTAKE` will allow you to withdraw pending principal immediately.

### Claim Rewards

Interest is generated after each epoch ends. The interest will be settled and added to `MY CLAIMABLE REWARDS`. Users can then `CLAIM REWARDS` to transfer the interest to their wallet, as shown below:

![Claim Rewards](/files/XUV1wVm2dZWeY4G6hyeI)

### Claim Principal

If you no longer wish to stake, you can withdraw all your principal by clicking `CLAIM PRINCIPAL AMOUNT`, as shown below:

![Claim Principal](/files/ZGqT4KCHDs64j67tA3oW)

### Operation Records

Scroll down further to view your activity history in this grid, including actions such as `Staking`, `Unstaking`, `Claim Principal`, and `Claim Rewards`.

![Operation Records](/files/zUsJc6kHkazJKDY5B8bh)

## Staking Records

Click `VIEW STAKING RECORDS` to enter the Staking Records page, as shown below:

![My Staking Records](/files/4wAhdwWeqt8ISgws4sm4)

The page shows an overview of all your staking activity across all grids, including:

* `My Stake Grids`: The number of slots you have staked in.
* `My Staking Amount in Pool`: The total staked amount earning interest.
* `Pending Staking Amount`: The total pending staked amount, which will take effect in the next epoch.
* `Claimable Principal Amount`: The total amount of principal available for withdrawal.
* `MY CLAIMABLE REWARDS`: The total rewards available for claiming.
* `MY ACCUMULATED REWARDS`: The total accumulated rewards.
*

Scroll down to see the list of all slots you have staked in:

![My Staking](/files/HFNvoggoLbFQjp7rRCz4)

Click `MANAGE` to go to the Manage Staking page mentioned earlier.

## Leverage Stake Grids

The right frame of the Staking page is for staking grid owners.

![Leverage Stake Grids](/files/NI43yOfA68UHyvUnCq22)

Click `BID FOR STAKE GRIDS` to go to the Auction page. Detailed rules can be found in the `Auction` section. Click `MANAGE MY STAKE GRIDS` to go to the My Stake Grids page, with details in the `My Stake Grids` section.


# Auction

## All Auctions

As shown below, all auctioned staking grids are displayed here. The auction status can be one of three types: `Auction Not Started`, `Auction In Progress`, and `Auction Ended`.

![All Auctions](/files/A4dY2vsnzKOI0OIKWKTx)

* (1) Auction Not Started

Enter the `Auction Not Started` details page to view the basic properties of the slot.

![Auctions Details](/files/QBZ3hH2YQTDqyqVBOT3Q)

You cannot bid yet, as the `BID NOW` button is disabled. Bidding is allowed only once the auction begins.

* (2) Auction In Progress

![Auctions In Progress](/files/Dzznjkb3qUNF5s4uYlVU)

Enter the `Auction In Progress` details page to view the current highest bid and all bid records. You can place a bid by clicking `BID NOW`, which will trigger a bidding pop-up:

![Auction Bid](/files/e5SaVUKaSXOVrcAlyAlc)

The pop-up will show the starting bid and increment amount. Your bid must be greater than or equal to the sum of the current highest bid and the increment amount. Once successfully placed, your bid will be displayed, as shown below:

![Auction](/files/9XUuStn7jd0xRY08lX8s)

* (3) Auction Ended

After the auction ends, you can see whether your bid was successful or not.

As shown in the image, there are three statuses for the staking grids you participated in bidding on: `AUCTION IN PROGRESS`, `AUCTION ENDED SUCCESSFUL`, and `AUCTION ENDED FAILED`.

![My Auctions](/files/4VbOsKKzswKXoke8jEMl)

For the staking grids that were successfully auctioned, you can go to `My Stake Grids -> Uninstalled` to view and install them.


# Staking Grid

This page shows all the staking grids you own, which are categorized into two statuses: `Installed` and `Uninstalled`.

![My Staking Grids List](/files/7mdC5LvVJlKHa71hH76S)

The list displays all installed storage grids, where you can see the node-related information and staking overview for each grid.

## Install Grid

### BOND WORKER

Before a grid is officially open for staking, you need to `BOND WORKER` and start the node, as shown in the image below:

![Bond Worker](/files/02RdosrHU52GZswk10Wk)

If you’re unsure how to start the node, please click to view the help manual.

Click `EDIT FEE` to customize the fee for the epoch, as shown in the image below:

![Edit Epoch Fee](/files/avWvIX6QDolTZUV154Lx)

### Stake Grid Details

Click `STAKE GRID` to view the grid’s details and staking overview.

![Edit Grid Details](/files/1GKvVKYLqKYwAxuzTCBi)

Scrolling down in the Stake Grid Details page, you can see the staking overview for the current period:

![Staking Grid Details](/files/rs6qraMHOBChqNqRSZSZ)

* `VALID STAKING AMOUNT`: TOTAL STAKING AMOUNT \* LIVING RATIO
* `VALID STAKING QUOTA`: VALID STAKING AMOUNT / Platform-wide VALID STAKING AMOUNT
* `STAKING REWARD`: VALID STAKING QUOTA \* Platform Total Reward
* `LIVING RATIO`: This parameter measures the uptime of the node (the higher the value, the higher the rewards).

Scrolling further down, you can see all staking records under the grid.

![Grid Staking Records](/files/TjHIcYK0l6KM5vZ1fTRK)

## Uninstalled

This list shows all uninstalled grids, allowing you to install or transfer them.

![Grid Uninstalled](/files/HlR6ldEjBcbD4ryDekPO)

Click `INSTALL STAKE GRID` to display the pop-up below. Set the fee and submit to complete the installation.

![Enter the Staking Fee](/files/lCQJYdyzN1SiDu1twuak)

Click `ASSIGN TO ADDRESS` to display the pop-up below. Enter the recipient's address. Upon submission, the wallet will prompt for gas payment. Once paid, the transfer is successful.

![Assign Address](/files/Ya6E0Zo8vtHpiEX9cPlP)


# NuLink Worker Installer

## Overview

The NuLink Worker is the node to provide cryptographic service in the NuLink network. It provides Proxy Re-encryption service in the Horus network and it will provide more services such as ABE, IBE, ZKP and FHE in NuLink mainnet. Only grid maintainers are required to run the NuLink Worker node. By continuously operating the worker node, grid maintainers remain eligible for rewards within the network.

There are four steps to run a NuLink Worker:

1. Create Worker Account
2. Bond the Worker Account with your grid
3. Install NuLink Worker
4. Configure and Run a Worker node

**Warning:** Do not use same address for staker account and worker account. Make sure to generate a new one for worker account.

## Minimum System Requirements

* Debian/Ubuntu (Recommended)
* 30GB available storage
* 4GB RAM
* x86 architecture
* **Static IP address**
* **Exposed TCP port 9151, make sure it's not occupied**
* Nodes can be run on cloud infrastructure.

## Create Worker Account

Prepare an ETH type account for the Worker. We suggest creating a Worker account different from the staking account.

If you already know how to create one and access the keystore file, you can skip this step. Otherwise we recommend you to use Geth to create the Worker account. Please check [here](/products/stakers/nulink_worker/eth_account) for details.

## Bond the Worker Account with your grid

Bond the worker account to your grid to get reward after successfully running a NuLink Worker node using the NuLink Staking Dashboard.

* Navigate to [NuLink Staking Dashboard](https://dashboard.testnet.nulink.org) and go to My Stake Grid Page
* Select the grid you wish to bond and Click “Bond Worker” button
* Enter the Worker address and Click “BOND” button
* Sign the bond transaction in metamask

![bond](/files/Lpugw8DCsntN0t81kD6o)

## Install NuLink Worker

Start to download and install NuLink Worker. Install it using Docker (recommended) or install it with local installation. See [here](/products/stakers/nulink_worker/worker_install) for more details.

## Initialize and Run a Worker Node

Initialize the configuration and start the Worker Node. If install via docker, need to initialize the configuration and run it in Docker. Otherwise please check [here](/products/stakers/nulink_worker/worker_running) for more details regarding local running.

After successfully running a worker node, you can check the Grid Status in the NuLink Staking Dashboard to confirm that it’s online or not.

![status](/files/FQuWTbBLXiqJSiFzRCBb)

Refer [here](/products/stakers/dashboardoverall) for more usage of NuLink Staking Dashboard.


# Create Worker Account

There are several ways to install Geth, including through the package manager, downloading the pre-built package, running as a docker container, or building from the downloaded source code. Please refer [here](https://geth.ethereum.org/docs/install-and-build/installing-geth) for more details regarding Geth Installation.

After installing Geth, it will save the keystore file to the local storage. Please remember the keystore file path and account address for later use.

## Example on Ubuntu

This section will demonstrate how to generate a Worker account using the official build package provided by Ethereum on Ubuntu.

1. Download [Geth](https://geth.ethereum.org/downloads/), select the installation packages of various versions applicable to different systems.

```shell
wget https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.10.23-d901d853.tar.gz
```

2. Unzip the downloaded installation package

```shell
tar -xvzf geth-linux-amd64-1.10.23-d901d853.tar.gz
```

3. Enter the unzipped directory

```shell
cd geth-linux-amd64-1.10.23-d901d853/
```

4. Use. / get account new -- keystore. / keystore to generate Ethereum account and keystore

```shell
./geth account new --keystore ./keystore
```

5. You will be prompted to enter the password and confirm the password. **Please remember this password for late use.**

Example：

```shell
INFO [09-08|15:30:11.904] Maximum peer count                       ETH=50 LES=0 total=50
INFO [09-08|15:30:11.905] Smartcard socket not found, disabling    err="stat /run/pcscd/pcscd.comm: no such file or directory"
Your new account is locked with a password. Please give a password. Do not forget this password.
Password: 
Repeat password: 

Your new key was generated


Public address of the key:   0x8B1819341BEc211a45a2186C4D0030681cccE0Ee
Path of the secret key file: /root/geth-linux-amd64-1.10.23-d901d853/keystore/UTC--2022-09-13T01-14-32.465358210Z--8b1819341bec211a45a2186c4d0030681ccce0ee

- You can share your public address with anyone. Others need it to interact with you.
- You must NEVER share the secret key with anyone! The key controls access to your funds!
- You must BACKUP your key file! Without the key, it's impossible to access account funds!
- You must REMEMBER your password! Without the password, it's impossible to decrypt the key!
```


# NuLink Worker Installation

NuLink worker node can be run from a docker container.

## Docker install and update

1. Install [Docker Engine](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository)
2. Pull the latest NuLink image.

   ```shell
   docker pull nulink/nulink:latest
   ```
3. Create a directory in your host machine for later usage.

   ```shell
   cd /root

   mkdir nulink
   ```
4. Copy the keystore file of the Worker account to the host directory selected in step 3. The private file generated by NuLink Worker will also be stored in this directory.

   ```shell
   cp /root/geth-linux-amd64-1.10.23-d901d853/keystore/* /root/nulink
   ```

   **Please ensure that this directory has 777 permissions**:

   ```shell
   chmod -R 777 /root/nulink
   ```


# NuLink Worker Initialization and Running

After installing the worker node via Docker, you can initialize and run it by following these three steps:

1. **Export Node Environment Variables**
2. **Initialize Node Configuration**
3. **Launch the Node**

**You have to deposit a small amount of the testnet BNB (tBNB) into the worker account to facilitate the sending of a confirmation transaction.**

## Export Node Environment Variables

To streamline the Docker installation procedure, we utilize certain environment variables. These variables are crucial for the operation of the NuLink Worker.

Select a password with at least 8 characters to lock and unlock the private storage created by the NuLink Worker. **It's important to remember this password for future access.**

```shell
export NULINK_KEYSTORE_PASSWORD=<YOUR NULINK STORAGE PASSWORD>
```

This password is used to unlock the keystore file of your Worker account. You would have established this password when creating the Worker account via Geth. Make sure you enter the same one!!!

```shell
export NULINK_OPERATOR_ETH_PASSWORD=<YOUR WORKER ACCOUNT PASSWORD>
```

## Initialize Node Configuration

This step creates and stores the NuLink worker node configuration, and only needs to be run once.

```shell
$ docker run -it --rm \
-p 9151:9151 \
-v </path/to/host/machine/directory>:/code \
-v </path/to/host/machine/directory>:/home/circleci/.local/share/nulink \
-e NULINK_KEYSTORE_PASSWORD \
nulink/nulink nulink ursula init \
--signer <ETH KEYSTORE URI> \
--eth-provider <NULINK PROVIDER URI>  \
--network <NULINK NETWORK NAME> \
--payment-provider <PAYMENT PROVIDER URI> \
--payment-network <PAYMENT NETWORK NAME> \
--operator-address <WORKER ADDRESS> \
--max-gas-price <GWEI>
```

Replace the following values with your own value:

* `</path/to/host/machine/directory>` - The host directory you create when install.
* `<ETH KEYSTORE URI>` - The path to the keystore file of the Worker account.
* `<NULINK PROVIDER URI>` - The URI of a local or hosted node where the Horus network launched.
* `<NULINK NETWORK NAME>` - The name of the network where the Horus network launched.
* `<PAYMENT PROVIDER URI>` - The URI of a local or hosted node where payment goes.
* `<PAYMENT NETWORK NAME>` - The name of the payment network.
* `<OPERATOR ADDRESS>` - The address of the Worker account. [How to generate Worker account](/products/stakers/nulink_worker/eth_account).
* `<GWEI>` (Optional) - The maximum price of gas to spend on any transaction.

Example Input:

```shell
docker run -it --rm \
-p 9151:9151 \
-v /root/nulink:/code \
-v /root/nulink:/home/circleci/.local/share/nulink \
-e NULINK_KEYSTORE_PASSWORD \
nulink/nulink nulink ursula init \
--signer keystore:///code/UTC--2022-09-13T01-14-32.465358210Z--8b1819341bec211a45a2186c4d0030681ccce0ee \
--eth-provider https://data-seed-prebsc-2-s2.binance.org:8545 \
--network horus \
--payment-provider https://data-seed-prebsc-2-s2.binance.org:8545 \
--payment-network bsc_testnet \
--operator-address 0x8B1819341BEc211a45a2186C4D0030681cccE0Ee \
--max-gas-price 10000000000
```

Example Output:

```shell
# step 1
 Detected IPv4 address (8.219.186.125) - Is this the public-facing address of Ursula? [y/N]: y
 
 Please provide a password to lock Operator keys.
 Do not forget this password, and ideally store it using a password manager.
 
 # step 2
 Enter nulink keystore password (8 character minimum): xxxxxx
 Repeat for confirmation: xxxxxx
 
 Backup your seed words, you will not be able to view them again.
 
 xxxxxxxxxxxxxxxxxxxxxxxx
 
 # step 3
 Have you backed up your seed phrase? [y/N]: y
 
 # step 4
 Confirm seed words: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 
 
Public Key:   02bb2067d21a677ce928967c0ece79a9
Path to Keystore: /home/circleci/.local/share/nulink/keystore

- You can share your public key with anyone. Others need it to interact with you.
- Never share secret keys with anyone! 
- Backup your keystore! Character keys are required to interact with the protocol!
- Remember your password! Without the password, it's impossible to decrypt the key!


Generated configuration file at default filepath /home/circleci/.local/share/nulink/ursula.json

* Review configuration  -> nulink ursula config
* Start working         -> nulink ursula run

```

## Launch the Node

Before performing this step, make sure that the environment variable has been set successfully. You can verify it using the following method, execute the following command:

```shell

root@xxx:~#echo $NULINK_KEYSTORE_PASSWORD
12345678
root@xxx:~#echo $NULINK_OPERATOR_ETH_PASSWORD
12345678
```

If the password is not displayed, please reset the environment variables.

```shell
export NULINK_KEYSTORE_PASSWORD=<YOUR NULINK STORAGE PASSWORD>
export NULINK_OPERATOR_ETH_PASSWORD=<YOUR WORKER ACCOUNT PASSWORD>
```

The following command will start the node. Make sure you use the same host directory as the configuration.

**Remark1: You need to** [**claim**](https://testnet.binance.org/faucet-smart) **some BNB(test) token for Worker account as gas fee.**

**Remark2: If you encounter error when starting Worker node, first please check that the port 9151 has not been occupied by other process. If still not working, please check there is only one configuration json file in the \</path/to/host/machine/directory>**

```shell
$ docker run --restart on-failure -d \
--name ursula \
-p 9151:9151 \
-v </path/to/host/machine/directory>:/code \
-v </path/to/host/machine/directory>:/home/circleci/.local/share/nulink \
-e NULINK_KEYSTORE_PASSWORD \
-e NULINK_OPERATOR_ETH_PASSWORD \
nulink/nulink nulink ursula run --no-block-until-ready
```

Example Input：

```shell
docker run --restart on-failure -d \
--name ursula \
-p 9151:9151 \
-v /root/nulink:/code \
-v /root/nulink:/home/circleci/.local/share/nulink \
-e NULINK_KEYSTORE_PASSWORD \
-e NULINK_OPERATOR_ETH_PASSWORD \
nulink/nulink nulink ursula run --no-block-until-ready
```

Example Output:

```shell
aa3a0f6376b566473cbcde46b0e772feb4d3658188d2cbb424a1e94588d6d8eb
```

## Check Node Status for Worker Account

The following command describes how to view worker status.

```shell
docker logs -f <docker name>
```

Example Input:

```shell
docker logs -f ursula
```

Example Output:

```shell
Authenticating Ursula
Loaded Ursula (horus)
✓ External IP matches configuration
Starting services
✓ Node Discovery (Horus)
✓ Work Tracking
✓ Start Operator Bonded Tracker
✓ Rest Server https://8.219.186.125:9151
Working ~ Keep Ursula Online!

```

Now the Worker address(e.g: 0x8B1819341BEc211a45a2186C4D0030681cccE0Ee) is ready for bonding operation.

## Restart the Worker Node

Occasionally, the staker may find it necessary to restart the worker node. Below is the command for restarting the currently running nodes:

```shell
docker restart <container ID>
```


# NuLink Worker Update

The NuLink worker node need to be updated when a new version is released. The update in docker is simple: stop the node, pull the latest image and restart the node.

1. Stop the running node in Docker:

   ```shell
   docker kill <container ID>
   ```

   Delete the container:

   ```shell
   docker rm <container ID>
   ```
2. Pull the latest NuLink image.

   ```shell
   docker pull nulink/nulink:latest
   ```
3. Re-launch the worker node.

   ```shell
   docker run --restart on-failure -d \
   --name ursula \
   -p 9151:9151 \
   -v /root/nulink:/code \
   -v /root/nulink:/home/circleci/.local/share/nulink \
   -e NULINK_KEYSTORE_PASSWORD \
   -e NULINK_OPERATOR_ETH_PASSWORD \
   nulink/nulink nulink ursula run --no-block-until-ready
   ```


# NuLink for DApp Builders

If you are new to the NuLink network and looking to develop a privacy-preserving Dapp, we recommend using the NuLink Agent directly. Integrating the NuLink Agent-SDK into your Dapp will automatically enable communication between your Dapp and the NuLink Agent.

If you already have a deeper understanding of the NuLink network, you can utilize the NuLink SDK to perform more fundamental operations in developing your Dapp. We offer a demonstration Dapp to exhibit the seamless integration of the NuLink SDK into applications.

## Using NuLink Agent-SDK

To start developing your Dapp with the NuLink Agent-SDK, follow these steps:

1. **Read the Documentation:** Explore the [NuLink Agent-SDK documentation](/products/dapp_builders/agent_sdk) to understand the functionalities and usage of the NuLink Agent-SDK.
2. **Integrate NuLink Agent-SDK:** Follow the integration guide provided in the documentation to seamlessly incorporate the NuLink Agent-SDK into your Dapp.
3. **Explore Demonstration Dapp:** Refer to the [NuLink Agent-SDK Demonstration Dapp](/products/dapp_users/agent_usecase) to get a hands-on tutorial on how Dapps interact with the [NuLink Agent](/products/dapp_users/nulink_agent) in a real-world scenario.

## Using NuLink SDK

For Dapp builders with a deeper understanding of the NuLink network, the [**NuLink SDK**](/products/dapp_builders/sdk_api) offers more fundamental operations for developing privacy-focused applications.

* [**NuLink SDK Demo:**](/products/dapp_builders/sdk_api/sdk_example) This Dapp serves as an illustrative example for third-party users, demonstrating how they can incorporate the NuLink SDK to enhance interaction with their own applications. The demo showcases the integration of the NuLink SDK, enabling features such as encrypted file uploads, privacy sharing, and targeted user downloads. The SDK demo consists of two parts: the first part demonstrates the process of integrating encrypted privacy sharing, while the second part showcases the utilization of the web interface to encrypt and upload files to the distributed network for specified users. By integrating the SDK, developers can harness the capabilities of the NuLink network for secure document transfers and data sharing.


# NuLink Agent SDK

The NuLink Agent SDK is a robust toolkit designed to empower developers in seamlessly integrating [NuLink Agent](https://github.com/NuLink-network/docs/blob/main/product/product/nulink_agent.md) functionality into their decentralized applications (DApps). Bridging the communication between DApps and the NuLink Agent, this comprehensive SDK provides essential software development tools and resources. You can use it in the browser or in a Node.js runtime. By incorporating the NuLink Agent SDK into your DApp, you enable a secure and efficient connection to the NuLink Agent, which acts as an intermediary for handling privacy-sensitive data requests,such as connect, upload data, apply, approve, and download.

Explore the potential of the NuLink Agent SDK with this documentation, guiding you through the integration process to create DApps that prioritize privacy and innovative functionalities.

## Environment

The following is the supported blockchain and its associated chain ID for your reference.

| Network                | Chain ID |
| ---------------------- | -------- |
| Horus (BSC Testnet)    | 97       |
| Conflux eSpace Testnet | 71       |

The following are the URLs for the NuLink Agent:

* Testnet: <https://agent.testnet.nulink.org>

## Getting Started

## Install

To get started, you need to install the NuLink Agent SDK into your project using either of the following commands:

```bash
npm i @nulink_network/nulink-web-agent-access-sdk
```

or

```bash
yarn add @nulink_network/nulink-web-agent-access-sdk
```

## Initial configration

After the installation, you'll need to set the configurations in the .env file of your project:

* REACT\_APP\_NULINK\_AGENT\_URL: the web agent address
* REACT\_APP\_CENTRALIZED\_SERVER\_URL: the backend service address
* REACT\_APP\_STAKING\_SERVICE\_URL: the staking service address
* REACT\_APP\_BSC\_TESTNET\_PORTER\_URL: the porter service address
* REACT\_APP\_DEFAULT\_NETWORK\_CHAIN\_ID: the network chain id

Here's an example of how to modify the .env file in your project:

```
// modify .env in your project
// web agent address
REACT_APP_NULINK_AGENT_URL=xxxxxx
// agent backend service address
REACT_APP_CENTRALIZED_SERVER_URL=xxxxxx
// staking service address
REACT_APP_STAKING_SERVICE_URL=xxxxxx
// porter service address
REACT_APP_BSC_TESTNET_PORTER_URL= xxxxxx
// chain Id
REACT_APP_DEFAULT_NETWORK_CHAIN_ID=xx
```

The following lists the default configuration in the NuLink Agent SDK:

* NuLink web agent address: <https://agent.testnet.nulink.org>
* Backend service address: <https://agent-integration-demo.nulink.org/bk>
* NuLink staking service address: <https://staking-api.testnet.nulink.org>
* NuLink porter service address: <https://porter-api.testnet.nulink.org>
* The network chain id: 97

## How to use

* [Interacting with NuLink Agent](#interacting-with-nulink-agent)
* [Upload data](#upload-data)
* [Apply Data](#apply-data)
* [Approve the apply data as publisher](#approve-the-apply-data-as-publisher)
* [Download data](#download-data)

### Interacting with NuLink Agent

The most common action is Sign In, where the user is redirected to the Wallet page to authorize the application. Once the user has successfully signed in, an access key is stored in the browser's LocalStorage. Subsequent actions that require the access key will be permitted.

```typescript
    import { connect } from "@nulink_network/nulink-web-agent-access-sdk"

    const gotoConnect = async () => {
        await connect(loginSuccessHandler)
    }
    
    const loginSuccessHandler: CallBackFunc = async (responseData) => {
        if (responseData) {
            // Do something with the responseData
            console.log(responseData);
        } else {
            // Handle the error case
            console.error('Failed to login in');
        }
    }
```

When the connect interface is called, the browser will be redirected to NuLink Agent, where user authentication is performed on the Agent side. Once the authentication is completed, the agent-access-sdk will store the user information in the LocalStorage of the calling side, indicating that the login process has been completed.

### Upload data

There are four interfaces available for uploading data as publisher: uploadData, uploadDataBatch, uploadFile, and uploadFileBatch. By calling these upload interfaces, you can navigate to the Agent upload page to complete the upload. After the upload is completed, you will receive the dataLabel and dataHash of the uploaded data.

```typescript
import { uploadData } from "@nulink_network/nulink-web-agent-access-sdk"

const _uploadAction = async () => {
    await uploadData({ dataLabel : dataLabel, fileBinaryArrayBuffer: blob }, async (responseData) => {
      if (responseData) {
        // Do something with the responseData
        console.log(responseData.dataInfo);
      } else {
        // Handle the error case
        console.error('Failed to upload');
      }
    })
}
```

```typescript
import { uploadDataBatch } from "@nulink_network/nulink-web-agent-access-sdk"

const _uploadAction = async () => {
    await uploadDataBatch(dataList, async (responseData) => {
      if (responseData) {
        // Do something with the responseData
        console.log(responseData.dataInfo);
      } else {
        // Handle the error case
        console.error('Failed to upload');
      }
    })
}
```

```typescript
import { uploadFile } from "@nulink_network/nulink-web-agent-access-sdk"

const _uploadAction = async () => {
    await uploadFile( file, async (responseData) => {
      if (responseData) {
        // Do something with the responseData
        console.log(responseData.dataInfo);
      } else {
        // Handle the error case
        console.error('Failed to upload');
      }
    })
}
```

```typescript
import { uploadFileBatch } from "@nulink_network/nulink-web-agent-access-sdk"

const _uploadAction = async () => {
    await uploadFileBatch( files, async (responseData) => {
      if (responseData) {
        // Do something with the responseData
        console.log(responseData.dataInfo);
      } else {
        // Handle the error case
        console.error('Failed to upload');
      }
    })
}
```

![uploaddata.png](/files/yQQboqbOiT6EWHc4GFuF)

By calling the `getFileList` API, you can retrieve all the uploaded data within the Agent.

### Apply Data

When applying for data, you can use the apply method from the Agent SDK to pass the file information to NuLink Agent. This will open the application page of NuLink Agent where you can complete the application process. The file information can be obtained from the `getFileList` and `getFileDetail` API.

```typescript
import { apply } from "@nulink_network/nulink-web-agent-access-sdk"

const applyForFile = async () => {
  await apply(_dataName, _dataId, _dataCreatorAddress, _dataUrl, _dataHash, _zkProof, _usageDays, async () => {
    if (responseData) {
      // Do something with the responseData
      console.log(responseData);
    } else {
      // Handle the error case
      console.error('Failed to upload');
    }
  });
};
```

![applyData.png](/files/b2XX0BrQT6lzegHcnJF1)

You can retrieve the data that the user has applied for by using the `getSendApplyFiles` function In the response data of `getSendApplyFiles`, the value of the "status" field indicates the approval status of the data, where 1 represents "applying" 2 represents "approved" and 3 represents "rejected"

### Approve the apply data as publisher

By calling the `getIncomingApplyFiles` function, you can retrieve all the incoming apply data of the user

![incomingdata.png](/files/jHuOeCsSNBNNXFvBIt6x)

calling the `approve` function, you can pass the data that needs to be approved to NuLink Agent. The data information can be obtained from the `getIncomingApplyFiles` API. The number of backup nodes required for the `approve` method can be obtained by calling the `getUrsulaNumber` API

![approvedata.png](/files/ZDZIbF8z4zCHmtvS9Wau)

In the response data of `getIncomingApplyFiles`, the value of the "status" field indicates the approval status of the data, where 1 represents "applying" 2 represents "approved" and 3 represents "rejected"

### Download data

Once the data requested by the user is approved, it can be downloaded

calling the `download` function, you can pass the information for downloading the data to NuLink Agent. The `download` function will return the binary buffer of the downloaded data

#### Example

```typescript
import { download }  from "@nulink_network/nulink-web-agent-access-sdk"

const fileDownload = async () => {
    await download(
        detailItem.file_id,
        detailItem.file_name,
        detailItem.file_hash,
        detailItem.creator_address,
        detailItem.file_zk_poof,
        detailItem.file_url,
        detailItem.file_encrypted_size,
        fileDownloadCallBack,
    );
};

const fileDownloadCallBack = async (data) => {
    try {
        if (!!data && data.arrayBuffer) {
            const blob = new Blob([data.arrayBuffer], { type: 'arraybuffer' })
            const url = window.URL.createObjectURL(blob)
            const link = document.createElement("a");
            link.style.display = "none";
            link.href = url
            link.setAttribute("download", data.fileName);
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    }catch (error){
        throw new Error("Decryption failed, Please try again")
    }
}
```

![downloaddata.png](/files/Zx7fU8dT9L7CLFZ5OwZj)

## Utilities

The default network for the NuLink Agent SDK is Horus (BSC Testnet), with a chain ID of 97

`getNetWorkChainId` can be used to retrieve information about the current chain ID. `setNetWorkChainId` can be used to change the chain ID.

Explore the [nulink-web-agent-integration-demo](https://github.com/NuLink-network/nulink-web-agent-integration-demo.git) repository for a practical example of Dapp integration with the NuLink Agent SDK.


# API Reference

All APIs take a callback function as a parameter and execute the callBackFunc after the corresponding method is successfully executed.

The callback function type that takes an optional parameter responseData and returns a Promise object. When the API call returns, the callback function is called with the responseData parameter, which is the data returned from the API call. The callback function can then process the data and handle any errors that occurred during the API call.

**CallBackFunc**

```typescript
type CallBackFunc =  ( responseData?:any ) => Promise<any>;
```

## Methods

### Workflow API

* [connect](#connect)
* [uploadData](#uploaddata)
* [uploadDataBatch](#uploaddatabatch)
* [uploadFile](#uploadfile)
* [uploadFileBatch](#uploadfilebatch)
* [apply](#apply)
* [approve](#approve)
* [download](#download)

### Platform data API

* [getFileList](#getfilelist)
* [getFileDetail](#getfiledetail)
* [getSendApplyFiles](#getsendapplyfiles)
* [getIncomingApplyFiles](#getincomingapplyfiles)
* [getUrsulaNumber](#getursulanumber)
* [getNetWorkChainId](#getnetworkchainid)
* [setNetWorkChainId](#setnetworkchainid)
* [sendCustomTransaction](#sendcustomtransaction)

### connect

```typescript
connect(callBackFunc:CallBackFunc)
```

`connect` is used for handling login functionality for nulink web agent. It opens a new window for the user to complete the login process, and then executes the callBackFunc with the login data when the login is successful.

#### Parameters

* Promise : CallBackFunc - A callback function that will be called with the response data from the server.

#### Returns

```
{
    accountAddress: string - the address of the logged-in user
    accountId: string - the ID of the logged-in user
    action: 'login' - the action type
    result: string
    redirectUrl: string
}
```

#### Example

```typescript
import { connect } from "@nulink_network/nulink-web-agent-access-sdk"

const gotoConnect = async () => {
    await connect(loginSuccessHandler)
}

const loginSuccessHandler: CallBackFunc = async (responseData) => {
  if (responseData) {
    // Do something with the responseData
    console.log(responseData);
  } else {
    // Handle the error case
    console.error('Failed to login in');
  }
}
```

### uploadData

```typescript
uploadData(_uploadData: UploadData, callBackFunc:CallBackFunc)
```

`uploadData`used for uploading data and executing a callback function after the upload is successful

```
type UploadData = {
    dataLabel : string,
    fileBinaryArrayBuffer: Blob
}
```

#### Parameters

* \_uploadData: UploadData - The type UploadData is defined as an object with properties dataLabel of type string and fileBinaryArrayBuffer of type Blob
* Promise : CallBackFunc - A callback function that will be called with the response data from the server

#### Returns

```
 {
    accountAddress: string
    accountId: string
    action: 'upload'
    subAction?: string
    dataInfo?: [{dataHash: string, dataLabel : string}]
    result: 'success' | 'failed'
    redirectUrl: string
    errorMsg?: any
}
```

#### Example

```typescript
import { uploadData } from "@nulink_network/nulink-web-agent-access-sdk"

const _uploadAction = async () => {
    await uploadData({ dataLabel : dataLabel, fileBinaryArrayBuffer: blob }, async (responseData) => {
      if (responseData) {
        // Do something with the responseData
        console.log(responseData.dataInfo);
      } else {
        // Handle the error case
        console.error('Failed to upload');
      }
    })
}
```

### uploadDataBatch

```typescript
uploadDataBatch(dataList: UploadData[], callBackFunc:CallBackFunc)
```

`uploadDataBatch` allows batch uploading of data and executes a callback function after the upload is successful

```
type UploadData = {
    dataLabel : string,
    fileBinaryArrayBuffer: Blob
}
```

#### Parameters

* dataList: UploadData\[] - an array of UploadData objects
* Promise : CallBackFunc - A callback function that will be called with the response data from the server

#### Returns

```
 {
    accountAddress: string
    accountId: string
    action: 'upload'
    subAction?: string
    dataInfo?: [{dataHash: string, dataLabel : string}]
    result: 'success' | 'failed'
    redirectUrl: string
    errorMsg?: any
}
```

#### Example

```typescript
import { uploadDataBatch } from "@nulink_network/nulink-web-agent-access-sdk"

const _uploadAction = async () => {
    await uploadDataBatch(dataList, async (responseData) => {
      if (responseData) {
        // Do something with the responseData
        console.log(responseData.dataInfo);
      } else {
        // Handle the error case
        console.error('Failed to upload');
      }
    })
}
```

### uploadFile

```typescript
uploadFile(file: File, callBackFunc:CallBackFunc)
```

`uploadFile` uploading file and executing a callback function after the upload is successful

#### Parameters

* file : File - the file to be uploaded, of type File
* Promise : CallBackFunc - A callback function that will be called with the response data from the server

#### Returns

```
 {
    accountAddress: string
    accountId: string
    action: 'upload'
    subAction?: string
    dataInfo?: [{dataHash: string, dataLabel : string}]
    result: 'success' | 'failed'
    redirectUrl: string
    errorMsg?: any
}
```

#### Example

```typescript
import { uploadFile } from "@nulink_network/nulink-web-agent-access-sdk"

const _uploadAction = async () => {
    await uploadFile( file, async (responseData) => {
      if (responseData) {
        // Do something with the responseData
        console.log(responseData.dataInfo);
      } else {
        // Handle the error case
        console.error('Failed to upload');
      }
    })
}
```

### uploadFileBatch

```typescript
uploadFileBatch(files: File[], callBackFunc:CallBackFunc)
```

`uploadFileBatch` allows batch uploading of file and executes a callback function after the upload is successful

#### Parameters

* files: File\[] - the files to be uploaded, an array of File
* Promise : CallBackFunc - A callback function that will be called with the response data from the server

#### Returns

```
 {
    accountAddress: string
    accountId: string
    action: 'upload'
    subAction?: string
    dataInfo?: [{dataHash: string, dataLabel : string}]
    result: 'success' | 'failed'
    redirectUrl: string
    errorMsg?: any
}
```

#### Example

```typescript
import { uploadFileBatch } from "@nulink_network/nulink-web-agent-access-sdk"

const _uploadAction = async () => {
    await uploadFileBatch( files, async (responseData) => {
      if (responseData) {
        // Do something with the responseData
        console.log(responseData.dataInfo);
      } else {
        // Handle the error case
        console.error('Failed to upload');
      }
    })
}
```

### apply

```typescript
apply(dataName: string,
      dataId: string,
      dataCreatorAddress: string,
      dataStorageUrl: string,
      dataHash: string,
      zkProof: string,
      usageDays: number,
      callBackFunc:CallBackFunc)
```

`apply` The apply function is used for applying for files, takes eight parameters: dataCreatorAddress,dataId,dataName,dataStorageUrl, dataHash,zkProof,usageDays and callBackFunc, which is the callback function to be executed after the application is successful.

#### Parameters

* dataName : string - The data name
* dataId : string - The data id
* dataCreatorAddress : string - The data creator Address
* dataUrl : string - The data storage url
* dataHash : string - The data hash
* zkProof : string - The data zkProof
* usageDays : number - The number of days applied
* Promise : CallBackFunc - A callback function that will be called with the response data from the server.

The parameters in the `apply` API can be obtained from the response of the `getFileList` `getFileDetail`

#### Returns

```
{
    accountAddress: string - the address of the logged-in user
    accountId: string - the ID of the logged-in user
    action: 'apply'
    subAction?: string
    owner: string - the file owner's address
    user: string - the file requester's address
    result: string
    redirectUrl: string
}
```

#### Example

```typescript
import { apply } from "@nulink_network/nulink-web-agent-access-sdk"

const applyForFile = async () => {
  await apply(_dataName, _dataId, _dataCreatorAddress, _dataUrl, _dataHash, _zkProof, _usageDays, async () => {
    if (responseData) {
      // Do something with the responseData
      console.log(responseData);
    } else {
      // Handle the error case
      console.error('Failed to upload');
    }
  });
};
```

### approve

```typescript
approve(applyId : string,
        applyUserAddress : string,
        applyUserId : string,
        dataName : string,
        dataHash : string,
        dataStorageUrl : string,
        days : string,
        backupNodeNum : number,
        callBackFunc : CallBackFunc)
```

`approve`is used for approving files, takes parameters: applyId, applyUserAddress, applyUserId, dataName, dataHash, dataUrl, days, backupNodeNum and callBackFunc.

#### Parameters

* applyId : string - the application ID
* applyUserId : string - the application user id
* applyUserAddress : string - the application user address
* dataName : string - The data name
* dataUrl : string - The data storage url
* dataHash : string - The data hash
* days : string - the application days
* backupNodeNum : number - number of nodes used for data backup, this number is the response of `getUrsulaNumber` API
* Promise : CallBackFunc - A callback function that will be called with the response data from the server.

#### Returns

```
{
    accountAddress: string - the address of the logged-in user
    accountId: string - the Id of the logged-in user
    action: string
    subAction?: string
    from: string - the file owner's address
    to: string - the file requester's address
    applyId: string - the apply id
    result: string
    redirectUrl: string
}
```

#### Example

```typescript
import { approve } from "@nulink_network/nulink-web-agent-access-sdk"

const approveSubmit = async () => {
    await approve(_applyId, _applyUserId, _applyUserAddress, _dataName, _dataUrl, _dataHash,  _days, _backupNodeNum, async () => {
      if (responseData) {
        // Do something with the responseData
        console.log(responseData);
      } else {
        // Handle the error case
        console.error('Failed to upload');
      }
    });
  };
```

### download

```typescript
download(dataId:string,
         dataName:string,
         dataHash: string,
         ownerAddress:string,
         zkProof: string,
         dataUrl: string,
         encryptedDataSize: string,
         callBackFunc:CallBackFunc)
```

The dataDownload API provides the function of downloading files.

#### Parameters

* dataId : string - The ID of the data to be downloaded
* dataName : string - The name of the data to be downloaded
* dataHash : string - The hash of the data to be downloaded
* ownerAddress : string - The owner of the data
* zkProof : string - The zk proof of the data
* dataUrl : string - The data storage url
* encryptedDataSize - The size of encrypted data
* Promise : CallBackFunc - A callback function that will be called with the response data from the server.

#### Returns

```
{
  accountAddress: string
    accountId: string
    fileName: string
    action: 'decrypted'
    subAction?: string
    result: 'success' | 'failed'
    redirectUrl: string
    arrayBuffer?: string - The ArrayBuffer of the raw data
    errorMsg?: any
}
```

#### Example

```typescript
import { download }  from "@nulink_network/nulink-web-agent-access-sdk"

const fileDownload = async () => {
    await download(
        detailItem.file_id,
        detailItem.file_name,
        detailItem.file_hash,
        detailItem.creator_address,
        detailItem.file_zk_proof,
        detailItem.file_url,
        detailItem.file_encrypted_size,
        fileDownloadCallBack,
    );
};

const fileDownloadCallBack = async (data) => {
    try {
        if (!!data && data.arrayBuffer) {
            const blob = new Blob([data.arrayBuffer], { type: 'arraybuffer' })
            const url = window.URL.createObjectURL(blob)
            const link = document.createElement("a");
            link.style.display = "none";
            link.href = url
            link.setAttribute("download", data.fileName);
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    }catch (error){
        throw new Error("Decryption failed, Please try again")
    }
}
```

### getFileList

```typescript
getFileList(accountId:string, include:boolean, desc:boolean = false, pageNum:number, pageSize:number)
```

Get the list of files belonging to other users.

#### Parameters

* accountId : string - ID of the currently logged-in user
* fileName : string - File name, supports fuzzy matching, can be empty.
* include : boolean - If include=false, exclude the files belonging to the current account; otherwise, the files belonging to the current user will be placed at the beginning of the list.
* format : string - the format of file,can be empty.
* desc : boolean - Whether to sort in descending order by upload time
* pageNum : number - page number (starting from 1)
* pageSize : number - page size

#### Returns

```typescript
{
    total: number
    list: [{
        file_id: string - the file ID
        file_name: string - the file name
        file_hash: string - the file hash
        file_raw_size: string - the original file size
        file_zk_proof: string - the zero-knowledge proof of file
        file_encrypted_size: string - The size of the encrypted file
        category: string - the file category/type
        format: string - file format
        suffix: string - file suffix
        address: string - file address
        thumbnail: string - file thumbnail
        owner: string - file owner
        file_url: string - file storage url
        address: string - the file hash in backend
        owner_id: string - file owner's account ID
        owner_avatar: string - file owner's avatar
        created_at: number - file upload timestamp
    }]
}
```

#### Example

```typescript
import { getFileList }  from "@nulink_network/nulink-web-agent-access-sdk"

const pageChange = async () => {
    let result = await getFileList(
        accountId, include, desc, pageNum, pageSize
    );
    dealWithResultList(result);
  };

```

### getFileDetail

```typescript
getFileDetail(fileId:string, fileUserAccountId:string)
```

get file details

#### Parameters

* fileId : string - the file id
* fileUserAccountId : string - The file user's account ID, which refers to the current user's account ID.

#### Returns

```typescript
[{
    file_id: string - File ID
    file_name: string - File name
    file_hash: string - the file hash
    file_raw_size: string - the original file size
    file_zk_proof: string - the zero-knowledge proof of file
    file_encrypted_size: string - The size of the encrypted file
    thumbnail: string - File thumbnail
    creator: string - Owner of the file (policy creator)
    creator_id: string - Owner ID of the file (policy creator ID)
    creator_avatar: string - Owner avatar of the file (policy creator avatar)
    creator_address: string - Ethereum address of the file owner (policy creator's address)
    file_created_at: number - File upload timestamp
    apply_id: number - Application record ID
    proposer_address: string - Ethereum address of the file user (policy user's address)
    status: number - Application status, 0: not applied, 1: applying, 2: approved, 3: rejected
    apply_start_at: string - Application start timestamp (policy start timestamp)
    apply_end_at: string - Application end timestamp (policy end timestamp)
    apply_created_at: string - Submit application timestamp
    policy_id: number - Policy ID
    hrac: string - Policy HRAC
    consumer: string - Policy user (applicant, file user)
    consumer_id: string - Policy user ID
    gas: string - Policy gas
    tx_hash: string - Policy transaction hash
    policy_created_at: string - Policy creation timestamp
    file_ipfs_address: string - File IPFS address
    policy_encrypted_pk: string - Encrypted public key of the policy
    encrypted_treasure_map_ipfs_address: string - Policy treasure map address
    alice_verify_pk: string - File owner's Verify public key
}]
```

#### Example

```typescript
import { getFileDetail }  from "@nulink_network/nulink-web-agent-access-sdk"

const _getFileDetail = async () => {
    let result = await getFileDetail(
        fileId, fileUserAccountId
    );
    dealWithdETAILResult(result);
  };

```

### getSendApplyFiles

```typescript
getSendApplyFiles(proposerId:string, status:number, pageNum:number, pageSize:number)
```

Function to fetch send application files

#### Parameters

* proposerId: string - Applicant's account ID
* status: number - Application status 0:no distinction, 1: applying, 2: approved, 3: rejected, 4: in progress, 5: expired
* pageNum: number - the page number
* pageSize: number - the page size

#### Returns

```typescript
[{
    file_id: string - File ID
    file_name: string - File name
    file_hash: string - the file hash
    file_raw_size: string - the original file size
    file_zk_proof: string - the zero-knowledge proof of file
    file_encrypted_size: string - The size of the encrypted file
    thumbnail: string - File thumbnail
    apply_id: number - Application record ID
    proposer: string - Applicant name
    proposer_id: string - Applicant account ID
    proposer_address: string - Applicant's address
    file_owner: string - File owner name
    file_owner_id: string - File owner account ID
    file_owner_address: string - File owner's address
    status: number - Application status, 1: applying, 2: approved, 3: rejected
    remark: string - Approval comment or remark
    start_at: number - Application start timestamp
    end_at: number - Application end timestamp
    created_at: number - Application timestamp
    policy_id: number - Policy ID
    policy_label_id: string - Policy label ID
    hrac: string - Policy HRAC code
}]
```

#### Example

```typescript
import { getSendApplyFiles }  from "@nulink_network/nulink-web-agent-access-sdk"

const _getSendApplyFiles = async () => {
    let result = await getSendApplyFiles(
        proposerId, status, pageNum, pageSize
    );
    dealWithResultList(result);
};

```

### getIncomingApplyFiles

```typescript
getIncomingApplyFiles(fileOwnerId:string, status:number, pageNum:number, pageSize:number)
```

Function to fetch the received application files

#### Parameters

* fileOwnerId: string - File owner's account ID
* status: number - Application status 0:no distinction, 1: applying, 2: approved, 3: rejected, 4: in progress, 5: expired
* pageNum: number - the page number
* pageSize: number - the page size

#### Returns

```typescript
[{
    file_id: string - File ID
    file_name: string - File name
    file_hash: string - the file hash
    file_raw_size: string - the original file size
    file_zk_proof: string - the zero-knowledge proof of file
    file_encrypted_size: string - The size of the encrypted file
    thumbnail: string - File thumbnail
    apply_id: number - Application record ID
    proposer: string - Applicant name
    proposer_id: string - Applicant account ID
    proposer_address: string - Applicant's address
    file_owner: string - File owner name
    file_owner_id: string - File owner account ID
    file_owner_address: string - File owner's address
    status: number - Application status, 1: applying, 2: approved, 3: rejected
    remark: string - Approval comment or remark
    start_at: number - Application start timestamp
    end_at: number - Application end timestamp
    created_at: number - Application timestamp
    policy_id: number - Policy ID
    policy_label_id: string - Policy label ID
    hrac: string - Policy HRAC code
}]
```

#### Example

```typescript
import { getIncomingApplyFiles }  from "@nulink_network/nulink-web-agent-access-sdk"

const _getIncomingApplyFiles = async () => {
    let result = await getIncomingApplyFiles(
        proposerId, status, pageNum, pageSize
    );
    dealWithResultList(result);
};

```

### getUrsulaNumber

```typescript
getUrsulaNumber()
```

Function to fetch the backup nodes number of ursula

#### Parameters

```
None
```

#### Returns

```typescript
    ursulaNumber : number 
```

#### Example

```typescript
import { getUrsulaNumber }  from "@nulink_network/nulink-web-agent-access-sdk"

let ursulaNum = await getUrsulaNumber()

```

### getNetWorkChainId

```typescript
getNetWorkChainId()
```

Function to get the network info

#### Parameters

None

#### Returns

```typescript
    chinId: number - the network chain id
```

#### Example

```typescript
import { getNetWorkChainId }  from "@nulink_network/nulink-web-agent-access-sdk"

const _getNetWorkChainId = async () => {
    let chainId = await getNetWorkChainId();
    // do something
};

```

### setNetWorkChainId

```typescript
getNetWorkChainId(chainId : string )
```

Function to get the network info

#### Parameters

```typescript
    chainId : string - the network chain id which you will set
```

#### Returns

None

#### Example

```typescript
import { setNetWorkChainId }  from "@nulink_network/nulink-web-agent-access-sdk"

const _setNetWorkChainId = async () => {
    await getNetWorkChainId(97);
    // do something
};

```

### sendCustomTransaction

```typescript
  sendCustomTransaction(callBackFunc:CallBackFunc, toAddress: string, rawTxData?: string, value?: string, gasPrice?: string)
```

send custom transaction by agent website

#### Parameters

* Promise: CallBackFunc - A callback function that will be called with the response data from the server.
* toAddress: string - The recevier of the transaction.
* rawTxData?: string - The call data of the transaction, can be empty for simple value transfers.
* value?: string - The value of the transaction in wei.
* gasPrice?: string - The gas price (wei) set by this transaction, if empty, it will use web3.eth.getGasPrice()

#### Returns

```typescript
{
  accountAddress: string - the address of the logged-in user
  accountId: string - the Id of the logged-in user
  toAddress: string - The receiving address
  rawTxData?: string - The call data of the transaction
  value?: string - The value of the transaction in wei
  gasPrice?: string - The gas price (wei) set by this transaction
  action: string - "transaction"
  subAction?: string
  result: string - 'success' or 'filed'
  transactionHash?: string - the transaction hash, if success
  errorMsg?: any - the error message
}
```

#### Example

```typescript
import {
  sendCustomTransaction
} from "@nulink_network/nulink-web-agent-access-sdk";

const sendTransaction = async () => {
  await sendCustomTransaction(sendTransactionCallBack, toAddress, null, value)
}

const sendTransactionCallBack = async (data) => {
  try {
    if ('success' == data.result){
        //do something
    } else {
        //do something
    }
  } catch (error) {
    throw new Error("Transaction failed, Please try again");
  }
};
```


# NuLink SDK

NuLink SDK is a software development kit designed to support privacy computing in the NuLink network.

## Build & Install

### Build Source

#### Set up your environment

1. select a configuration file of your usage environment

* Development Environment (.env.dev)
* Production Environment (.env.prod)
* Custom Environment (.env.example)

2. Rename configuration file to .env

* for Development Environment: rename .env.dev to .env
* for Production Environment: rename .env.prod to .env
* for Custom Environment: rename .env.example to .env, [then you need to modify the configuration file manually](#customEnvConfig)

**Set configuration for a custom environment**

```javascript
//Modify config:
//the sdk backend testnet server address. in the nulink testnet,
//you can use the address: https://agent.testnet.nulink.org/bk
REACT_APP_CENTRALIZED_SERVER_URL=xxxxx

//Configure the parameters of the network that you connect to. Parameters for networks that are not connected do not need to be configured.

//the nulink bsc testnet porter address. in the nulink testnet,
//you can use the address: https://agent.testnet.nulink.org/porter
REACT_APP_BSC_TESTNET_PORTER_URI= xxxxx
//the network's (e.g. bsc testnet) web3 rpc url. example:
REACT_APP_BSC_TESTNET_WEB3_RPC_URL=xxxxx
```

#### build project

```shell
1. yarn install
2. yarn build:main
```

### Install via npm

```bash
npm i @nulink_network/nulink-sdk
```

or

```bash
yarn add @nulink_network/nulink-sdk
```

## API docs

### The Classes

* `NulinkHDWallet`: The module mainly includes interfaces for nulink wallet related operations.
* `AccountManager`: The module mainly responsible for managing multiple Account objects. AccountManager is a property of the NulinkHDWallet wallet object.
* `Account`: The module mainly includes interfaces for nulink wallet account related operations. Account is a property of the AccountManager object.
* `Strategy`: The module is mainly used to encrypt user files for file uploading using private keys.

### The Functions

* `Functions`: The module mainly includes interfaces for file encryption and uploading, as well as operations related to interacting with the blockchain.

[API Details](/products/dapp_builders/sdk_api/modules)

## Usage Example

See [NuLink SDK Examples](/products/dapp_builders/sdk_api/sdk_example) to get how to use NuLink SDK.


# API Reference

[NuLink SDK - v0.5.31](/products/dapp_builders/sdk_api) / Modules

## NuLink SDK - v0.5.31

### Table of contents

#### Enumerations

* [DataType](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/enums/DataType.md)
* [DataCategory](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/enums/DataCategory.md)

#### Classes

* [Strategy](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/classes/Strategy.md)
* [Account](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/classes/Account.md)
* [AccountManager](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/classes/AccountManager.md)
* [NuLinkHDWallet](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/classes/NuLinkHDWallet.md)

#### Type Aliases

* [DataInfo](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/types/DataInfo.md)
* [GasInfo](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/types/GasInfo.md)

#### Data Apply Details Functions

* [getApplyDetails](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getApplyDetails.md)
* [getMultiApplyDetails](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getMultiApplyDetails.md)

#### Data Publisher(Alice) Approval Functions

* [getPolicyServerFee](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getPolicyServerFee.md)
* [getPolicyGasFee](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getPolicyGasFee.md)
* [ApprovalUseData](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/ApprovalUseData.md)
* [getPolicyTokenCost](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getPolicyTokenCost.md)
* [estimatePolicyGas](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/estimatePolicyGas.md)
* [approvalApplicationForUseData](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/approvalApplicationForUseData.md)
* [refusalApplicationForUseData](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/refusalApplicationForUseData.md)

#### Data Publisher(Alice) Approval (Multi) Functions

* [getPolicysServerFee](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getPolicysServerFee.md)
* [getPolicysGasFee](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getPolicysGasFee.md)
* [ApprovalMultiUseData](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/ApprovalMultiUseData.md)
* [getPolicysTokenCost](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getPolicysTokenCost.md)
* [estimatePolicysGas](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/estimatePolicysGas.md)
* [approvalApplicationsForUseData](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/approvalApplicationsForUseData.md)
* [refusalApplicationsForUseData](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/refusalApplicationsForUseData.md)

#### Data Publisher(Alice) Approval Details Functions

* [getDataForApprovedAsPublisher](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataForApprovedAsPublisher.md)
* [getDataForAllStatusAsPublisher](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataForAllStatusAsPublisher.md)
* [getDataByStatusForAllApplyAsPublisher](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataByStatusForAllApplyAsPublisher.md)
* [getDataAllStatusAsPublisher](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataAllStatusAsPublisher.md)
* [getDataByApplyStatusAsPublisher](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataByApplyStatusAsPublisher.md)
* [getDataPendingApprovalAsPublisher](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataPendingApprovalAsPublisher.md)
* [getApprovedDataAsPublisher](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getApprovedDataAsPublisher.md)
* [getDataForRefusedAsPublisher](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataForRefusedAsPublisher.md)
* [getDataByStatus](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataByStatus.md)

#### Data Publisher(Alice) Data Details Functions

* [checkDataApprovalStatusIsUnderReviewOrApproved](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/checkDataApprovalStatusIsUnderReviewOrApproved.md)
* [getDataInfoByStatus](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataInfoByStatus.md)
* [getUploadedData](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getUploadedData.md)
* [getDataInfosByAccount](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataInfosByAccount.md)
* [deleteUploadedData](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/deleteUploadedData.md)
* [checkDataApprovalStatusIsApprovedOrApproving](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/checkDataApprovalStatusIsApprovedOrApproving.md)
* [checkMultiDataApprovalStatusIsApprovedOrApproving](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/checkMultiDataApprovalStatusIsApprovedOrApproving.md)
* [getDataInfosByPolicyId](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataInfosByPolicyId.md)
* [getDataDetails](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataDetails.md)

#### Data Publisher(Alice) Download Data Functions

* [getDataContentAsPublisher](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataContentAsPublisher.md)
* [getDataContentByDataIdAsPublisher](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataContentByDataIdAsPublisher.md)

#### Data Publisher(Alice) Policys Functions

* [getPublishedPolicyInfos](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getPublishedPolicyInfos.md)
* [getDataInfoOfPolicy](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataInfoOfPolicy.md)
* [getAllDataInfoOfPolicy](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getAllDataInfoOfPolicy.md)
* [getPublishedPoliciesInfo](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getPublishedPoliciesInfo.md)
* [getPoliciesInfo](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getPoliciesInfo.md)

#### Data Publisher(Alice) Upload Data Functions

* [uploadDataByCreatePolicy](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/uploadDataByCreatePolicy.md)
* [uploadDataBySelectPolicy](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/uploadDataBySelectPolicy.md)

#### Data User(Bob) Approval Details Functions

* [getDataAllStatusAsUser](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataAllStatusAsUser.md)
* [getDataByApplyStatusAsUser](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataByApplyStatusAsUser.md)
* [getDataPendingApprovalAsUser](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataPendingApprovalAsUser.md)
* [getApprovedDataAsUser](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getApprovedDataAsUser.md)
* [getUnapprovedDataAsUser](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getUnapprovedDataAsUser.md)
* [getDataByStatus](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataByStatus.md)

#### Data User(Bob) Data Details Functions

* [checkDataApprovalStatusIsUnderReviewOrApproved](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/checkDataApprovalStatusIsUnderReviewOrApproved.md)
* [getDataApprovedForApplicantAsUser](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataApprovedForApplicantAsUser.md)
* [getDataByStatusForAllApplyAsUser](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataByStatusForAllApplyAsUser.md)
* [getDataInfoByStatus](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataInfoByStatus.md)
* [getOtherShareData](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getOtherShareData.md)
* [checkDataApprovalStatusIsApprovedOrApproving](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/checkDataApprovalStatusIsApprovedOrApproving.md)
* [checkMultiDataApprovalStatusIsApprovedOrApproving](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/checkMultiDataApprovalStatusIsApprovedOrApproving.md)
* [getDataDetails](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataDetails.md)

#### Data User(Bob) Download Data Functions

* [getDataForApprovedAsUser](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataForApprovedAsUser.md)
* [getApprovedFileContentUrl](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getApprovedFileContentUrl.md)
* [getApprovedDataContent](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getApprovedDataContent.md)
* [getDataContentAsUser](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataContentAsUser.md)
* [getDataContentByDataIdAsUser](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataContentByDataIdAsUser.md)

#### Data User(Bob) Policys Functions

* [getPolicyInfosAsUser](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getPolicyInfosAsUser.md)
* [getDataInfoOfPolicy](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDataInfoOfPolicy.md)
* [getAllDataInfoOfPolicy](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getAllDataInfoOfPolicy.md)
* [getInUsePoliciesInfo](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getInUsePoliciesInfo.md)
* [getPoliciesInfo](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getPoliciesInfo.md)

#### Data User(Bob) Request Data Functions

* [applyForDataUsagesPermission](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/applyForDataUsagesPermission.md)
* [applyForDataUsagePermission](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/applyForDataUsagePermission.md)
* [revokePermissionApplicationOfData](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/revokePermissionApplicationOfData.md)

#### Send Raw Transaction Functions

* [sendCustomTransaction](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/sendCustomTransaction.md)
* [estimateCustomTransactionGas](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/estimateCustomTransactionGas.md)

#### Wallet Account Functions

* [getLoginedUserInfo](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getLoginedUserInfo.md)
* [isUserLogined](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/isUserLogined.md)
* [getUserDetails](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getUserDetails.md)
* [getUserByAccountId](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getUserByAccountId.md)
* [updateUserInfo](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/updateUserInfo.md)
* [restoreWalletDataByRootExtendedPrivateKey](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/restoreWalletDataByRootExtendedPrivateKey.md)
* [restoreWalletDataByMnemonic](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/restoreWalletDataByMnemonic.md)
* [restoreWalletData](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/restoreWalletData.md)
* [exportWalletData](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/exportWalletData.md)
* [createWallet](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/createWallet.md)
* [loadWallet](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/loadWallet.md)
* [verifyPassword](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/verifyPassword.md)
* [existDefaultAccount](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/existDefaultAccount.md)
* [logoutWallet](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/logoutWallet.md)
* [getWalletDefaultAccount](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getWalletDefaultAccount.md)
* [unlockWallet](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/unlockWallet.md)
* [getMnemonic](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getMnemonic.md)
* [getDefaultAccountPrivateKey](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getDefaultAccountPrivateKey.md)
* [createAccountIfNotExist](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/createAccountIfNotExist.md)
* [IsExistAccount](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/IsExistAccount.md)
* [createAccount](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/createAccount.md)
* [getAccountInfo](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getAccountInfo.md)
* [getAccountInfos](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/getAccountInfos.md)
* [updateAccountInfo](https://github.com/NuLink-network/docs/blob/main/product/builder/sdk_api/functions/updateAccountInfo.md)


# Usage Example

## Usage

### SelectNetworks

When nulink supports multiple networks, users can set their preferred network using the following method:

```javascript

import {setCurrentNetworkKey} from "@nulink_network/nulink-sdk";

 //The currently available network: NETWORK_LIST.Horus
await setCurrentNetworkKey(NETWORK_LIST.Horus)

```

### Set Data Storage

Since the purpose of nulink pre is to encrypt and share data (files), it inevitably involves uploading (storing) and downloading (retrieving) files. Therefore, it is necessary to set up the methods for accessing files. The process is as follows:

first, we need to import package

```javascript

import {
  StorageManager,
  DataCallback,
  setIPFSData,
  getIPFSData,
} from '@nulink_network/nulink-sdk'
```

Then, you need to implement the setData and getData methods of the DataCallback structure. Since we need to upload data (files) in batches in our use case, while usually retrieving them one by one, we need to implement the setData method for batch uploading and the getData method for retrieving data individually.

```javascript

const dataCallback: DataCallback = { setData: setIPFSData, getData: getIPFSData }
  //Set the external storage used by the Pre process to IPFS (for example, encrypted files uploaded by users will be stored in this storage, and users can customize the storage).
  StorageManager.setDataCallback(dataCallback)

```

After setting up the callback functions, when we upload files using the uploadDataByCreatePolicy method in pre, the callback function setData you have set will be automatically invoked. Later, when we retrieve files using getDataContentAsUser, the getData function will be automatically called.

The setData and getData types are as follows:

```javascript

export type DataCallback = {
    setData: AsyncSetDataCallback;
    getData: AsyncGetDataCallback;
};

export type AsyncSetDataCallback = ((data: DataType, account: Account) => Promise<string[]>) | ((data: DataType) => Promise<string[]>);

export type AsyncGetDataCallback = (key: string) => Promise<Buffer | Uint8Array | null | undefined>;

```

Notes:

```
Please note that the Account parameter is optional. If the setData callback function defined by the user requires account information (such as signing data with the account's private key), the callback function can be defined with an additional parameter for the account. In the pre process, when the setData callback function is called, the account information will be passed to the user-defined callback function, allowing the callback function to access the current account information (account parameter).
```

More details:

For more information, you can refer to this example: [upload.backend.ts](https://github.com/NuLink-network/nulink-sdk/blob/crosschain/src/core/utils/external-storage/implement/upload.backend.ts)

If the account parameter is not needed, you can refer to this example: [ipfs.ts](https://github.com/NuLink-network/nulink-sdk/blob/crosschain/src/core/utils/external-storage/implement/ipfs.ts)

<br>

### With these preparations done, we can now proceed to the code for the pre process

```
Here's the story: We have two characters in our story. One is named Alice, who uploads the data. The other is Bob, who wants to use the data uploaded by Alice. So, Bob requests Alice's uploaded data in our network. Once Alice sees Bob's request in our system, she has the option to either reject the request, in which case Bob cannot access the data, or approve Bob's request. If Alice approves the request, she can send an on-chain approval transaction, and upon successful approval, Bob can download the file to view or use it.
```

### Create Wallet for Alice

First, In order to use the pre process, we need to first create an account.

```javascript

//First, we import all the required libraries.
import {
  isBlank,
  restoreWalletDataByMnemonic,
  getPolicyGasFee,
  type DataInfo,
  DataCategory,
  uploadDataByCreatePolicy,
  getUploadedData,
  createAccountIfNotExist,
  getOtherShareData,
  getDataDetails,
  applyForDataUsagePermission,
  getDataPendingApprovalAsPublisher,
  refusalApplicationForUseData,
  getPolicyTokenCost,
  approvalApplicationForUseData,
  getApprovedDataAsPublisher,
  getApprovedDataAsUser,
  getDataContentByDataIdAsUser,
  getPublishedPoliciesInfo,
  uploadDataBySelectPolicy,
  getDataByStatus,
  getMnemonic,
  getDefaultAccountPrivateKey,
  logoutWallet,
  GasInfo
} from "@nulink_network/nulink-sdk";

import assert from "assert-ts";

import { BigNumber, ethers } from "ethers";
import { nanoid } from "nanoid";
import Web3 from "web3";

// Declaring and intializing the mnemonic and password variables.
const password: string = "1";

//first We create Alice's wallet and account by password
const nuLinkHDWallet1: NuLinkHDWallet = await createWallet(password);

assert(nuLinkHDWallet1);

// after we created the wallet, we can loadWallet by password
const nuLinkHDWallet2: NuLinkHDWallet | null = await loadWallet(password);
assert(nuLinkHDWallet2);

const nuLinkHDWallet = nuLinkHDWallet2 as NuLinkHDWallet;

assert(nuLinkHDWallet1 === nuLinkHDWallet);

//also, We can verify whether the user's password is correct
const correct: boolean = await verifyPassword(password);

assert(correct);

// We can also determine if the user has created an account locally
const hasAnAccountInLocal: boolean = await existDefaultAccount();
assert(hasAnAccountInLocal);

// we can get the account by user password that we have created
const accountAlice: Account = (await getWalletDefaultAccount(password)) as Account;
assert(accountAlice);
```

### Alice upload data/files for encrypted

Next, we will upload data using the account we just created, which we'll refer to as "Alice."

```javascript

// account Alice: as the publisher of the file (file uploader).

// Note: We only support one account currently.

//Now we can encrypt and upload a file for others to apply for download

//1. read a file
const plainText = 'file-content....';
const enc = new TextEncoder(); // always utf-8
const historyContent: Uint8Array = enc.encode(plainText);

//1.Alice upload file
const dataList: DataInfo[] = [
  {
    //label: A unique identifier for the file (similar to the file name) that is displayed to the user who needs to apply for the file
    label: `history-${nanoid()}.pdf`,
    dataArrayBuffer: historyContent.buffer,
  },
];

//2. Alice encrypt and update a file to the ipfs network
await uploadDataByCreatePolicy(accountAlice, DataCategory.History, dataList);

//3. We can get the file just uploaded
const resultList = (await getUploadedData(accountAlice, undefined, 1, 1000)) as object;

console.log("resultList: ", resultList);
console.log('resultList["total"]>0 ', resultList["total"] > 0);
assert(resultList && resultList["total"] > 0);

let fileIndex = -1;
for (let index = 0; index < resultList["list"].length; index++) {
  const element = resultList["list"][index];
  if (element["file_name"] === dataList[0]["name"]) {
    fileIndex = index;
    break;
  }
}
assert(fileIndex >= 0);
const uploadDataInfo = resultList["list"][fileIndex];

assert(uploadDataInfo["owner_id"] === accountAlice.id);
```

### Bob requests to use the data/files uploaded by Alice

Then: Bob, far away on the other side of the ocean, wants to use Alice's uploaded data.

1.create wallet for Bob

```javascript
// Bob, far away on the other side of the ocean, wants to use Alice's uploaded data
//  account Bob: as the user of the data/file ( data/file requester)

//don't forget import libirary ....

//Bob find the  data/file on Internet
const password: string = "1";

//Create Wallet for Bob
//first We create Bob's wallet and account by password
const nuLinkHDWallet: NuLinkHDWallet = await createWallet(password);

assert(nuLinkHDWallet);

  // we can get the account by user password that we have created
  const _accountBob: Account = (await getWalletDefaultAccount(password)) as Account;
  assert(_accountBob);
```

2.Bob views the details of the data that Alice just uploaded by checking the online information of other users' uploaded data.

```javascript
//Bob finds the file Bob has just uploaded
const dataDataResultList = (await getOtherShareData(_accountBob,undefined, false, undefined,
undefined, undefined, 1, 1000
)) as object;

assert(dataDataResultList && dataDataResultList["total"] > 0);

let dataIndex2 = -1;
for (let index = 0; index < dataDataResultList["list"].length; index++) {
  const element = dataDataResultList["list"][index];
  if (element["file_name"] === dataList[0]["name"]) {
    dataIndex2 = index;
    break;
  }
}
assert(dataIndex2 >= 0);

const findDataInfo = dataDataResultList["list"][dataIndex2];
assert(findDataInfo["owner_id"] === accountAlice.id);

const applyDataId = findDataInfo["file_id"];

//get data details
const dataDetails = (await getDataDetails(applyDataId, _accountBob.id)) as object;

//assert(dataDetails["creator_id"] === accountAlice.id);
assert(dataDetails["file_id"] === applyDataId);
assert(parseInt(dataDetails["status"]) === 0); //Is not to apply for
```

3.Bob is particularly interested in the data uploaded by Alice. So, Bob requests to use the data that Alice has just uploaded.

```javascript
//Bob requests permission to use the data for 7 days
try {
  await applyForDataUsagePermission(applyDataId, _accountBob, 7);
} catch (e) {
  console.log("bob apply data failed", e);
  assert(false);
}
```

4.Alice reviews the usage requests from others for the data she uploaded.

At first, Alice rejected Bob's request to use the data.

```javascript
//Alice receives Bob's data usage request

// Alice reviews the usage requests from others for the data she uploaded.
const dataNeedToApprovedResultList = await getDataPendingApprovalAsPublisher(accountAlice, 1, 1000);

let fileIndex3 = -1;
for (
  let index = 0;
  index < dataNeedToApprovedResultList["list"].length;
  index++
) {
  const element = dataNeedToApprovedResultList["list"][index];
  if (element["file_id"] === applyDataId) {
    fileIndex3 = index;
    break;
  }
}
assert(fileIndex3 >= 0);

assert(dataNeedToApprovedResultList && dataNeedToApprovedResultList["total"] > 0);
const needToApprovedDataInfo =
  dataNeedToApprovedResultList["list"][fileIndex3];
assert(needToApprovedDataInfo["file_owner_id"] === accountAlice.id);

//Alice rejected the file usage request
await refusalApplicationForUseData(accountAlice, needToApprovedDataInfo["apply_id"]);
```

5.Bob finds this file to be very useful, so he makes a second request.

```javascript
//Bob apply file for usage again. The application period is three days, less than the previous seven days
try {
  await applyForDataUsagePermission(applyDataId, _accountBob, 3);
} catch (e) {
  console.log("bob reapply file failed", e);
  assert(false);
}
```

### Alice approves Bob's request to use the file

1.Alice is moved by Bob's persistence and after much consideration, she finally agrees to Bob's usage request.Since we need to send approval transactions to the current blockchain network, we first need to assess the gas fees as well as the service fees for requesting others' usage.

```javascript
//Alice receives Bob's file usage request again
const dataNeedToApprovedResultList2 = await getDataPendingApprovalAsPublisher(accountAlice, 1, 1000);

assert(
  dataNeedToApprovedResultList2 &&
    dataNeedToApprovedResultList2["total"] > 0
);

let dataIndex4 = -1;
for (
  let index = 0;
  index < dataNeedToApprovedResultList2["list"].length;
  index++
) {
  const element = dataNeedToApprovedResultList2["list"][index];
  if (element["file_id"] === applyDataId) {
    dataIndex4 = index;
    break;
  }
}
assert(dataIndex4 >= 0);

const needToApprovedDataInfo2 = dataNeedToApprovedResultList2["list"][dataIndex4];
assert(needToApprovedDataInfo2["file_owner_id"] === accountAlice.id);

//At this point Alice approves Bob's file usage request, Due to on-chain approval of Bob's request, we first evaluate gas and service fees

//1. Alice calc server fee (wei): 
//    For the main chain TBSC/BSC, the token is TNLK/NLK. 
//    For the side chains, they use the native currency of the respective chain (e.g., Mumbai uses TMATIC/MATIC, OKX X1 Chain uses TOKB/OKB).
const startDate: Date = new Date();
const startMs: number = Date.parse(startDate.toString());
const endMs: number =
  startMs + (needToApprovedDataInfo2["days"] as number) * 24 * 60 * 60 * 1000;
const endDate: Date = new Date(endMs); //  start_at is seconds, but Date needs milliseconds

const serverFeeNLKInWei: BigNumber = await getPolicyTokenCost(accountAlice, startDate, endDate, 2);

const serverValue = Web3.utils.fromWei(serverFeeNLKInWei.toString(), "ether");
console.log("server nlk fee  ether is:", serverValue);

//2. Alice calc gas fee (wei): the chain of bsc test token
const gasInfo: GasInfo = await getPolicyGasFee(
  _accountBob.id,
  needToApprovedDataInfo2["apply_id"],
  2,
  1,
  startMs/1000,
  endMs/1000,
  BigNumber.from(serverFeeNLKInWei)
);

//First, let's record the list of requests from other individuals that Alice has already approved, for future reference.
  const aliceApprovedfilesListLast = await getApprovedDataAsPublisher(
    accountAlice,
    1,
    1000
  );

//Note: Please make sure that the account has sufficient tnlk and bsc testnet tokens before this, otherwise the approval will fail
//Alice approves Bob's application for file usage. Whenever Alice approves a file request, an on-chain policy is created
await approvalApplicationForUseData(
  accountAlice,
  _accountBob.id,
  needToApprovedDataInfo2["apply_id"],
  2,
  1,
  startDate,
  endDate,
  "", //remark
  "", //porterUri
  gasInfo.gasFee
);
```

2.As it is an on-chain transaction, there might be some delay. At this point, we need to wait for the on-chain transaction to be successfully confirmed by web3 before Alice can view her latest list of approved documents.

```javascript

let aliceApprovedDataList: any = null;
  do {
    await sleep(10000); //10 seconds
    //Alice, as the publisher of the file, obtains the list of files that she has successfully approved
    aliceApprovedDataList = await getApprovedDataAsPublisher(
      accountAlice,
      1,
      1000
    );
    /*return data format: {
      list: [
        { apply_id, file_id:, proposer, proposer_id, file_owner:, file_owner_id:, policy_id, hrac, start_at:, end_at, created_at }
        ...
      ],
      total: 300,
    }
  */
  } while (
    !aliceApprovedDataList ||
    aliceApprovedDataList["total"] <= aliceApprovedfilesListLast["total"]
  );

  assert(aliceApprovedDataList && aliceApprovedDataList["total"] > 0);
```

### Bob checks his list of requested files, and he can use the data now

1.At this point, Bob checks his list of requested files and discovers that Alice has approved his request to use the file. So, Bob obtains the details of the document for future reference and downloading.

```javascript

//Record this policy ID and account Bob for future use.
let policyId;
let accountBob;
const dataIndex2s: number[] = [] //Array(numReqData).fill(-1);
  for (let index = 0; index < aliceApprovedDataList['list'].length; index++) {
    const element = aliceApprovedDataList['list'][index]
    if (element['file_id'] === applyDataId) {
      dataIndex2s.push(index)
      assert(element['file_owner_id'] === accountAlice.id)
      const _policyId = element['policy_id']
      policyId = _policyId;
      //console.log(`index_${index} data/file policy Id: ${_policyId}`)
      const accountBobId = element['proposer_id']
      const _accountBob = bobAccountId2AccountMap[accountBobId]
      accountBob = _accountBob;
      //Bob finds out that his application has been approved by Alice. Bob now has permission to view the contents of the file
      const bobBeApprovedDataList = await pre.getApprovedDataAsUser(_accountBob, 1, 1000)
      /*return data format: {
                              list: [
                                { apply_id, file_id:, proposer, proposer_id, file_owner:, file_owner_id:, policy_id, hrac,
                                  start_at:, end_at, created_at }
                                ...
                              ],
                              total: 300,
                            }
      */

      assert(bobBeApprovedDataList && bobBeApprovedDataList['total'] > 0)

      let dataIndex6 = -1
      for (let index = 0; index < bobBeApprovedDataList['list'].length; index++) {
        const element = bobBeApprovedDataList['list'][index]
        if (element['file_id'] === applyDataId) {
          dataIndex6 = index
          break
        }
      }
      assert(dataIndex6 >= 0)

      const bobBeApprovedDataInfo = bobBeApprovedDataList['list'][dataIndex6]
      assert(bobBeApprovedDataInfo['file_owner_id'] === accountAlice.id)
      const policyId2 = bobBeApprovedDataInfo['policy_id']
      assert(policyId2 === _policyId)

```

2.At this point, Bob downloads and views the data.

```javascript
      //Finally, Bob gets the contents of the data/file
      const arrayBuffer: ArrayBuffer = await pre.getDataContentByDataIdAsUser(
        _accountBob,
        bobBeApprovedDataInfo['file_id']
      )
      const dataContent: string = Buffer.from(arrayBuffer).toString()
      console.log('dataContent: ', dataContent)
      console.log('plainText: ', plainText)
      assert(dataContent === plainText)

      //finish
    }
  }

  assert(dataIndex2s.length >= 0 && dataIndex2s.length > 0)
  //finish
```

### Alice obtain the on-chain policy information published by herself

Also, Whenever Alice approves a file request, an on-chain policy is created. Alice can also obtain the on-chain policy information published by herself

```javascript

// Whenever Alice approves a file request, an on-chain policy is created
// Alice can also obtain the on-chain policy information published by herself
const dataPolicys = await getPublishedPoliciesInfo(accountAlice, 1, 1000);

assert(!isBlank(dataPolicys));
```

### Alice upload file by select Published Policy

1.Alice also can encrypt and update a file to the ipfs network by select an existing on-chain policy

```javascript
//Alice also can encrypt and update a file to the ipfs network by select an existing on-chain policy
const plainText2 = "This is a philosophy book content";
const historyContent2: Uint8Array = enc.encode(plainText2);

//1.upload file
const dataList2: DataInfo[] = [
  {
    label: `philosophy-${nanoid()}.pdf`,
    dataArrayBuffer: historyContent2.buffer,
  },
];

//Files/Data uploaded by using published policies do not need approval. Bob can use the files directly, so there is no approval record
const fileIds = await uploadDataBySelectPolicy(
  accountAlice,
  DataCategory.Philosophy,
  dataList2,
  policyId
);
```

### Bob get data no need approve by Alice's published policys

2.Bob can directly download Alice's associated policy upload file without waiting for Alice's approval, because the associated policy has already been created and does not need repeated approval.

```javascript
//Bob can directly download Alice's associated policy upload file without waiting for Alice's approval,
//because the associated policy has already been created and does not need repeated approval. Note: This publish policy value is available for Bob
//Bob get new upload file content
const arrayBuffer2: ArrayBuffer = await getDataContentByDataIdAsUser(
  _accountBob,
  fileIds[0]
);
const dataContent2: string = Buffer.from(arrayBuffer2).toString();
console.log("dataContent2: ", dataContent2);
console.log("plainText2: ", plainText2);
assert(dataContent2 === plainText2);

//you can get all status files for mine apply: The files I applied for
//status 0: all status, include:  applying, approved, rejected
const data = (await getDataByStatus(
  undefined,
  _accountBob.id,
  undefined,
  undefined,
  0,
  1,
  1000
)) as object;

assert(data && !isBlank(data) && data["total"] > 0);
```

### Restore wallet by mnemonic

For wallet more info, you can also restore wallet by mnemonic

```javascript
// we also can restore wallet by mnemonic

//get mnemonic from current wallet
const mnemonic: string = (await getMnemonic(password)) as string;

//You can also use the mnemonic word exported by metamask to restore the nulink wallet account
const newpassword = "111";
// restore an wallet to Browser localstorage/indexdb  by mnemonic, and we can set an new password when we restore an wallet
const nuLinkHDWalletRestore: NuLinkHDWallet =
  await restoreWalletDataByMnemonic(newpassword, mnemonic);
assert(nuLinkHDWallet != nuLinkHDWalletRestore);

//You can also export the private key of the nulink wallet account through the user password to import it into the metamask wallet
let privatekeyString = await getDefaultAccountPrivateKey(newpassword);
assert(privatekeyString != null);
privatekeyString = privatekeyString as string;

//When you are done using it, you can clear the browser's wallet cache data, and use the mnemonic to re-import it the next time you use it
await logoutWallet();
```

## API docs

[API Details](https://github.com/NuLink-network/nulink-sdk/tree/crosschain/docs/modules.md)

## More examples

[nulink-sdk-demo](https://github.com/NuLink-network/nulink-sdk-demo)


# NuLink for DApp Users

DApp users play a pivotal role in the NuLink ecosystem by leveraging the platform's privacy-centric solutions. Once connected to the NuLink network through SDK integrations, users can manage their privacy data seamlessly.As NuLink continues to evolve, DApp users remain at the forefront, experiencing enhanced privacy, security, and control over their interactions within the decentralized landscape. Explore the offerings tailored for DApp users:

## NuLink Agent

[NuLink Agent](/products/dapp_users/nulink_agent) serves as a versatile web-based digital wallet, fostering smooth communication between DApps and the NuLink network. Acting as a secure intermediary, it facilitates requests and responses, enhancing the overall user experience.

### Key Features:

* **Robust Endpoint Encryption:** NuLink Agent ensures strong encryption for endpoints, providing a robust layer of security for data in transit.
* **Secure Data Storage/Sharing:** The NuLink Agent facilitates secure storage and sharing of data, prioritizing the confidentiality and integrity of user information.
* **User-Friendly Access Control:** NuLink Agent offers a user-friendly access control system, enabling users to manage and control who can access their data with ease.
* **Transparent Transactions:** Users benefit from transparent and verifiable transactions, fostering accountability within the decentralized environment.

## NuLink Snaps (Coming Soon)

[NuLink Snaps](/products/dapp_users/nulink_snaps) introduces a groundbreaking approach to decentralized data management for Web3 DApps. This upcoming tool utilizes Private Key signatures, intergraed into MetaMask, offering users control over both digital assets and data privacy.


# NuLink Agent

## What is NuLink Agent?

NuLink Agent is a web-based digital wallet that differs from traditional plugin wallets in that it does not need to be installed on the browser. Instead, users can simply open a webpage and login to manage their NuLink private account data and digital assets, as well as interact with other DApps.

When browsing third-party DApps, if the application supports NuLink account authorization login, users can launch the NuLink Agent authorization login page for logging in. After logging in to the NuLink Agent account, users can perform a series of on-chain operations such as applying for fund account authorization, transferring funds, uploading files, and more. All of these operations will be recorded on the blockchain.

## Access NuLink Agent

* [NuLink Agent for Testnet](https://agent.testnet.nulink.org)
* NuLink Agent for Mainnet (In development...)

## Registration

Open NuLink Agent [https://agent.testnet.nulink.org ](https://agent.testnet.nulink.org)or <https://agent.nulink.org> (in development).

If you are a new user, you need to register by clicking `CREATE AN AGENT ACCOUNT` and proceed to the next step.

![Create Account](/files/4lMmAlb5nZ7Wg47ihO8y)

Enter the password setting page, where the password needs to be entered twice for confirmation. Make sure you can remember the password, which will be used to verify your identity during certain account security operations.

![Set Password](/files/6YfJbZir6q9eD928qUEs)

## Backup Mnemonic

After registration, it is essential to back up your mnemonic. The mnemonic is used to restore your account. Even if you change your computer, you can recover your account as long as you have your mnemonic.

After registration, it is essential to back up your mnemonics. The mnemonics are used to recover your account. Even if you switch computers, as long as you have the mnemonic phrase, you can retrieve your account. Click `Start backing up` to proceed.

![Backup Mnemonic](/files/WvXPQTlBY6RXSNqORxUs)

Here is your mnemonic phrases. You can click `Copy` to copy it to your computer, but it's best to handwrite it in your notebook to prevent accidental deletion or loss.

![Display Mnemonic](/files/5aYPPOlNczXuqK6KcCOC)

Finally, to ensure you have saved the mnemonic phrase correctly, verify the accuracy of the saved phrase by writing the corresponding words as prompted. A successful verification message will appear upon completion.

![Verify Mnemonic](/files/oUqGwTPDCA3eDghMK8je)

## Account Recovery

If you already have an account and have saved your mnemonic phrases, you can directly click `RESTORE YOUR ACCOUNT` on the "Home" page. Enter your mnemonic phrases and reset your password to successfully recover and log into your account.

![Restore Account](/files/1UazG1kaWAgI8cGszSIQ)

## Homepage

After registering or recovering your account, the page will automatically redirect to the account homepage, where you can see all your token balances. Currently, two types of tokens are supported: NLK and BNB. You can also view each of your transaction records.

![Homepage](/files/KjAVkBYTHg16C6cyYFsz)

## Transfer

After selecting the Token, click `Send` to enter the transfer page. Enter the "Receiver's address" and "Amount". You can also click `Max` to transfer all balances. After confirming the information, click `Next` to complete the transfer. A certain amount of gas fees will be charged for each transaction.

![Transfer](/files/RFXP8W19Vxh3vqCP44KG)

## Receive

Click `Receive` to display your account address and a QR code. The QR code contains your account address, which is convenient for others to scan and transfer without manual input.

![Receive](/files/djkbb3p5xVt4fZr8W4rE)

## Settings

Click `Setting`, switch to `Setup Network`. The system has preset the RPC URL. If you have a faster RPC URL, you can set it yourself for a better experience.

![Setting](/files/PPo5FH1I0BO7Co2CuNiE)

## Export Private Key

The private key contains all account information. The purpose of exporting the private key is to enable users to view their account information in other wallets. For example, users can import the private key of NuLink Agent to MetaMask to view their account information on NuLink Agent.

The private key contains all account information. The purpose of exporting the private key is to enable users to view their account information in other wallets. For example, you can view your NuLink Agent account information on Metamask by importing the NuLink Agent's private key.

![Export Private Keys](/files/70CGnEdzlmhSjXEidbi2)

Read the security tips carefully to ensure privacy during the export process. Click `EXPORT PRIVATE KEYS`, enter your account password, and you can view your private key.

![Enter Password](/files/AHkKizlo6Y6Pq9FCOU0l)

After obtaining the private key, click `COPY PRIVATE KEYS` below to quickly copy your private key. Follow the security tips below to keep your private key safe.

![Export Private Keys](/files/cNnPpP639YV5lf5geX5T)


# DApp Example

Welcome to the NuLink Agent SDK's third-party demonstration case, showcasing a private file-sharing platform known as [File Transfer](https://agent-integration-demo.nulink.org). This platform ensures privacy and security by encrypting all files uploaded and shared among users.

The workflow of File Transfer is simple and efficient:

* Users can freely upload and encrypt their files on the platform.
* Other users can apply for files they are interested in.
* Once the author approves the application, the applicant can download and view the encrypted files.

To maintain the utmost privacy and security of files, all operations within this platform are executed through on-chain contracts.

In the following sections, we will dive deeper into the detailed usage of this application and its seamless integration with the NuLink Agent.

This application requires authorization to log into the Agent account for normal access and operation.

![File Transfer Demo](/files/ln8zdY0o2gSZfQPPXano)

Click `Agent` in the top right corner to call up the Agent authorization page.

## Agent Authorization Login

Before official authorization, enter your account password and click `confirm` to start the authorization.

![Enter Password](/files/AHkKizlo6Y6Pq9FCOU0l)

As shown in the authorization page below, it displays the request source's address and my Agent account address.

![Connect NuLink Agent](/files/zfhj7gX6rblxldXuBmn3)

Click `Confirm` and the page will automatically return to the third-party application page.

The image below shows the third-party application 'File Transfer' page in the logged-in state, with the account being the currently logged-in Agent account.

![File Transfer](/files/Rch4b7Mm3TEhUpIospKX)

If you have not uploaded any files, please click `Upload File` first.

## File Upload -> Single File Upload

After selecting the local file to upload, you will be redirected to the Agent page to encrypt the file first, as shown below.

**Notice: the file size can not exceed 5M bytes.**

![File Upload](/files/kxjUE5oAumwJ73v5vZdb)

Click `NEXT` to start encryption.

After encryption, you will enter the file upload page, as shown below.

![File Upload Confirm](/files/N3d6AhZ7UowLQ1U5ltWp)

Click `CONFIRM` to start the file upload.

After successful file upload, the following interface will be displayed:

![File Upload Success](/files/6KIRkqHNxvu1vy0cfZ9y)

## File Upload -> Multiple File Batch Upload

After selecting the local files to upload, you will be redirected to the Agent page to encrypt the files first, as shown below.

![Multiple Files Upload](/files/Ii4zXzd7dxwrTd6rrmiZ)

Click the `Left Arrow` or `Right Arrow` buttons on the progress bar to switch and view each file's details. And click `NEXT` to start encryption.

After encryption, you will enter the file upload page, as shown below.

![Multiple Files Upload Confirm](/files/Hq1Vnj3Xld3Qznq4AYk5)

Click `CONFIRM` to start the file upload.

After successful file upload, the following interface will be displayed:

![Multiple Files Upload Success](/files/bWE8mHeGThEo6jXL3Enu)

## File Application

The figure below shows the file details page, and clicking "Request the file" can apply for the file. Enter the number of days you want to apply for and click "Submit."

The image below is the file detail page. Click `Request the file` to apply for the file.

![Request File](/files/uToDlZ70MJBwLoMr4AT6)

Enter the desired number of days and click `Submit`.

![Request Submit](/files/J6LkQBj3pksAEG4Hn14m)

Next, Agent will be called up for file application authorization, and the request details are shown below.

![Request Confirm](/files/UlKoTHW4dFjgJPKstugr)

Click `CONFIRM` to apply.

After completing the authorization application, you will return to the third-party application page, and the file status will change to `pending`.

![Rquest Pending](/files/oJRl4zMgPyHMgQGSjXYX)

## File Approval

The image below is the author's list page of received applications.

![Request Review](/files/ON9wzU4YxzeNDwZNCOlT)

* Single File Approval

Click `Review request` button next to the file list to view the application details, and click `Submit` if everything is fine.

![Request Review Submit](/files/pvGiNsNre9qy2c6LhluY)

* Multiple File Batch Approval Select multiple files you wish to apply for, then click `Review request` button. View the application details of the files, click the `Previous` and `Next` buttons to view different file application details, and click `Submit` if everything is fine.

![Request Review Submit](/files/rf44Z7Y8cKZYObV7DryW)

Then the Agent authorization page will be called up, and the details of the approval request are shown below. Click `APPROVE` to proceed with the approval.

![Request Approve](/files/pSotSeyo2jO4FkZ0xPvU)

After completing the approval, you will return to the third-party application page, and the file status will change to `Approved`.

![Request Approved](/files/hY0VzBrHXQfeiLxMoLPA)

## File Download

When the applicant re-enters the file details page, they will see that their request has been approved and they can now download the file.

![Approved File Info](/files/AxP3BpGyo6J3P9KoB4vK)

Click `Download now`. Since it is an encrypted file, the encrypted file will be downloaded first, click `NEXT`, as shown in the image below,

![Authorization Request](/files/fi6CCo0LXDJBSFMq8CPK)

further decrypt the file by clicking `Confirm`.

![File Decryption Confirm](/files/4GNRJQbLw10DEe5eNXzn)

A message indicating successful decryption will appear, and after 1 second, you will automatically return to the third-party application page.

![File Decrypted](/files/qwzC0hYg7jOsVz9dnYBR)

The image below shows the returned third-party page, and as shown in the lower left corner, the file has been downloaded to the local machine through the browser.

![The Main](/files/y7A9ledeZU1njTKyKq6U)

Click on the file to view its content, as shown below.

![File Image](/files/LBMAoqu4ayEOdzueAcVo)

## Storage Capacity

To meet users' needs for encrypted file storage capacity, Agent offers a storage capacity recharge plan for users, as shown in the image below.

![Storage Upgrade](/files/JGdRlUGUVeG0oQIKeeGI)

![Storage Plan Chose](/files/gtuJcqW95KQMoRVi3fuo)


# NuLink Snaps

Coming soon!!!


# Horus3.0 Testnet

Horus3.0 is NuLink's dedicated testnet designed for developers and community members to test and implement proprietary security infrastructure components within their Web3 applications.

## Horus3.0 Testnet Parameters

* **Blockchain:** [BNB Smart Chain Testnet](https://testnet.bscscan.com/)
* **Horus 3.0 Token address:** [0x3DE51dBD8737d8Fc3332F34fA1D2401F1E620f60](https://testnet.bscscan.com/address/0x3DE51dBD8737d8Fc3332F34fA1D2401F1E620f60)
* **Epoch Length:** 24 hours
* **Batch Length:** 7 epochs
* **Staking Rewards Per Epoch:** 100 TNLK
* **Minimal Staking Amount:** 1 TNLK

For the latest updates and progress, refer to our [testnet milestones](/products/testnet/horus_milestones). The Horus 3.0 testnet is only for test purposes. The token in the testnet has no value to trade. And for each phase, all data and records will be cleared, so please do not store your valuable data in Horus testnet.

## Testnet Components

1. **Supply Side Integration:**
   * Horus3.0 emphasizes the integration of proxy workers as the primary staking node. Developers can deploy and test proxy worker nodes to contribute services and earn test rewards.
   * Essential tools for stakers include the NuLink Staking Dashboard and NuLink Worker Node Installer, ensuring efficient management and deployment of staking activities.
2. **Demand Side Integration:**
   * Products for DApp builders and users are seamlessly integrated, allowing developers to test the functionality of their applications with privacy-focused solutions.
   * For DApp builders, integration with the NuLink Agent is supported, along with corresponding demonstration DApps.
   * DApps from NuLink's grant program are actively integrated, showcasing diverse applications on the Horus3.0 testnet.

## Demonstration DApps

1. **Secure File Transfer (NuLink Agent Demo):**
   * The "Secure File Transfer" DApp serves as a demonstration for the integration of NuLink Agent on the Horus3.0 testnet.
   * Users can experience the functionality of the NuLink Agent in a real-world scenario, emphasizing secure file transfers and data sharing.
2. **NuLink Snaps Showcase:**
   * A dedicated demonstration DApp for NuLink Snaps, allowing users to explore and understand the capabilities of decentralized end-to-end data management.

## Get Started

Getting started with the Horus3.0 Testnet is quick and easy. Follow the steps below based on your role to begin your journey with NuLink's cutting-edge Web3 data privacy solutions:

### For Stakers

1. **Set Up Your Development Environment:** Ensure you have a [suitable development environment](/products/stakers/nulink_worker#minimum-system-requirements) with the necessary tools for staking and worker node running.
2. **Acquire Test Tokens:** Head over to our [faucet in the dashboard](https://dashboard.testnet.nulink.org/) to claim your test tokens (tBNB and tNLK). These tokens are essential for participating in staking activities on the testnet.
3. **Stake Using the NuLink Staking Dashboard:** Utilize the [NuLink Staking Dashboard](broken://pages/gIAKEN5w6zOJLsfWYa9G) for efficient management and deployment of staking activities. Stake your test tokens to contribute services and earn test rewards.
4. **Deploy and Monitor Worker Node:** Deploy worker nodes using the [**NuLink Worker Installer**](/products/stakers/nulink_worker) and monitor your worker status in the Dashboard.

### For Builders

1. **Builder Your DAPP:** You can use our SDK([Nulink SDK](/products/dapp_builders/sdk_api),[Nulink Agent SDK](/products/dapp_builders/agent_sdk)) to develop dapps with functions such as privacy computing, data encryption and sharing, etc.
2. **Test Your DAPP:** You can get the test token from the [faucet in the dashboard](https://dashboard.testnet.nulink.org/) and test your dapp in our testnet

### For Users

1. **File Transfer DAPP:** We provide a [Demonstration DAPP](/products/dapp_users/agent_usecase) that users can use to participate in the process of privacy computing and encrypted data sharing.

Now you're all set to embark on your journey with NuLink's Horus3.0 Testnet. If you have any questions or need assistance, feel free to reach out to the community or our support channels. Happy testing!


# Testnet Milestones

Horus 3.0 is structured to evolve through three distinct phases, each bringing valuable features and enhancements to the NuLink testnet environment. Currently, we are in phase 1.

### Phase 1 (2023.Q4-2024,Q1)

1. **Staking Dashboard Release:**
   * [The NuLink Staking Dashboard](broken://pages/gIAKEN5w6zOJLsfWYa9G), a user-friendly interface for managing staking activities, will be released for testing.
2. **Worker Node Installer Testing:**
   * [The NuLink Worker Node Installer](/products/stakers/nulink_worker/worker_install), a tool simplifying the deployment of NuLink worker nodes, will be released for testing by the community.

### Phase 2

1. **NuLink Agent Integration:**
   * The [NuLink Agent](/products/dapp_users/nulink_agent) will be connected to the Horus 3.0 testnet, allowing developers to test and interact with this privacy-focused solution.
2. **NuLink Demo DApp Integration:**
   * A [demonstration DApp](/products/dapp_users/agent_usecase) showcasing NuLink functionalities will be connected to the testnet, providing hands-on experience for users and developers.
3. **Blockchain Support:**
   * Horus will expand its compatibility by supporting multiple blockchains, enhancing the versatility and accessibility of the testnet.

### Phase 3

1. **NuLink Snaps Release:**
   * NuLink Snaps, a decentralized end-to-end data management tool, will be officially released on the Horus 3.0 testnet.
2. **Storage Payment Mechanism Integration:**
   * The integration of NuLink's storage payment mechanism into the testnet, ensuring a comprehensive and functional environment.
3. **Grant Program DApp Deployment:**
   * DApps developed as part of NuLink's grant program will be deployed on the Horus 3.0 testnet, showcasing diverse applications within the ecosystem.

The phased development of Horus 3.0 on the NuLink testnet reflects our commitment to providing a robust, secure, and feature-rich environment for developers and users alike.


# Glossary

Welcome to the NuLink Glossary, where you can find key terms and their definitions related to NuLink's Web3-based ZK Provable Data Privacy Solutions.

## A

### Access Control

**Access Control** refers to the mechanisms, such as Proxy Re-Encryption (PRE) and Attribute-Based Encryption (ABE), implemented by NuLink to regulate and manage data access.

## B

### Bond

**Bond** is the process in NuLink where a staker establishes the mapping between their staking account and a service node, such as a worker node. After staking tokens in the dashboard, the staker initiates the bonding procedure to link their worker node to their staking activities. This linkage is essential for the network to recognize the staker's contributions and allocate rewards accordingly.

### Batch

A **Batch** in the NuLink network refers to a designated period, comprising multiple **epochs**. The specific length of a batch will be determined by the DAO in a late stage.

## C

### Claimable Deposit

**Claimable Deposit** represents the amount of deposit return to the staker after unstake. The staker can claim back in the staking dashboard.

### Claimable Reward

**Claimable Reward** refers to the reward earned by a staker within the NuLink network that can be claimed.

## D

### DAO (Decentralized Autonomous Organization)

The **Decentralized Autonomous Organization (DAO)** in NuLink is a self-governing entity that plays a crucial role in determining various network parameters, including the length of epochs, batches, etc. DAO decisions shape the overall governance and evolution of the NuLink ecosystem.

## E

### Endpoint Encryption

**Endpoint Encryption** is a privacy-preserving mechanism provided by NuLink. It enables the secure encryption of sensitive data at the endpoint (i.e., on the local device such as PC and smartphone).

### Epoch

An **Epoch** is a defined time period within a NuLink network batch. Key processes such as reward distribution and staker changes are orchestrated on an epoch-based timeline. This structured approach ensures that these activities are carried out at the conclusion of each epoch, offering an organized and predictable framework for managing NuLink network operations.

## F

### FHE (Fully Homomorphic Encryption)

**Fully Homomorphic Encryption (FHE)** is a cryptographic technique employed by NuLink to enable computations on encrypted data without the need for decryption.

## L

### Living Ratio

**Living Ratio** is a metric within the NuLink network that represents the proportion of stakers who are actively participating.

## P

### PRE (Proxy Re-Encryption)

**Proxy Re-Encryption (PRE)** is an access control mechanism used in NuLink. It allows for the secure sharing of sensitive data.

## R

### Reputation Score

**Reputation Score** is a metric in the NuLink network assesses a staker's historical contribution within a single batch. It counts the number of active epochs within a batch, considering epochs with a living ratio higher than a specified threshold (currently set to 0.8) as active. The reputation score serves as an indicator of a staker's reliability and positive engagement with the NuLink network

### Reputation Score Quota

**Reputation Score Quota** is a measurement represents the proportion of an individual user's reputation score relative to the total user's reputation score within the NuLink network. The metric provides insights into the relative contribution of a user's reputation to the overall reputation dynamics of the NuLink ecosystem.

## S

### Service Bonus

**Service Bonus** is intended to encourage stakers based on their performance. This bonus is generated from the service fees paid by users to the system. It reflects the active and valuable participation of stakers in delivering reliable and efficient services within the NuLink ecosystem.

### Stake

**Stake** is the process in NuLink where a staker deposits tokens into the pending pool. Tokens in the pending pool are scheduled to be counted in the staking pool starting from the next epoch. By staking, a staker commits tokens to participate in the NuLink network, securing it and becoming eligible for rewards based on the staked amount.

### Staker

A **Staker** is an entity within the NuLink network that actively participates in staking by providing services or computational resources. Stakers contribute to the network's operations and receive rewards in return.

### Staker Address

**Staker Address** is a unique identifier associated with a staker within the NuLink network. It serves as a reference for tracking and managing staking activities, rewards, and contributions.

### Staking Amount

**Staking Amount** represents the quantity of tokens a staker commits to the NuLink network as part of the staking process. This amount is a key factor in determining staking rewards and incentives for the staker.

### Staking Reward

**Staking Reward** is the reward earned by a staker within the NuLink network based on their staking activities and service performance.

## U

### Unbond

**Unbond** is the process in NuLink where a staker terminates the established mapping between their staking account and a service node, such as a worker node. By initiating the unbonding procedure, the staker discontinues the association between their staking activities and the worker node.

### Unstake

**Unstake** is the process in NuLink where a staker moves deposited tokens from the staking pool to the pending pool. Tokens in the pending pool can be claimed back by the staker in the next epoch.

## V

### Valid Staking Amount

**Valid Staking Amount** is a dynamically adjusted quantity of tokens committed by a staker to the NuLink network as part of the staking process. It is calculated by multiplying the staking amount by the living ratio. This adjustment ensures that the staker's contribution is proportionate to the overall engagement and participation of stakers within the network..

### Valid Staking Quota

**Valid Staking Quota** represents the percentage of the total valid staking capacity that a staker contributes to the NuLink network for a specific epoch. It is calculated by dividing the staker's valid staking amount by the total valid staking amount in that epoch. This metric provides insights into the relative contribution of an individual staker to the overall staking dynamics of the NuLink ecosystem.

## W

### Worker

A **Worker** is a participant in the NuLink network responsible for providing PRE services.

### Worker Address

**Worker Address** is the unique identifier associated with a worker node within the NuLink network.

## Z

### ZKP (Zero-Knowledge Proof)

**Zero-Knowledge Proof (ZKP)** is a cryptographic protocol used by NuLink to prove the authenticity of information without revealing the actual data.


# Release Notes

## For Stakers In Supply Side

| **Project**                                                                               | **Description**                                                                                                                                                                                                                              | **Current Version**                               | **Open Sourced** |
| ----------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ---------------- |
| [**`NuLink Worker Node`**](https://github.com/NuLink-network/nulink-core/tree/crosschain) | The NuLink Worker Node is the node to provide cryptographic service in the NuLink network. It provides Proxy Re-encryption service in the Horus network and it will provide more services such as ABE, IBE, ZKP and FHE in NuLink mainnet. . | [0.5.0](/resources/release_notes/notes_worker)    | Yes              |
| [**`NuLink Staking Dashboard`**](https://dashboard.testnet.nulink.org/)                   | A user-friendly interface empowering stakers to efficiently manage staking activities. It allows them to stake token, bond node, monitor contributions, track rewards, and ensure the smooth operation of NuLink services.                   | [0.5.0](/resources/release_notes/notes_dashboard) | No               |

## For DApp Builders In Demand Side

| **Project**                                                                      | **Description**                                                                                                                                                   | **Current Version**                               | **Open Sourced** |
| -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ---------------- |
| [**`NuLink Agent SDK`**](https://github.com/NuLink-network/nulink-web-agent-sdk) | The NuLink Agent-SDK provides developers with essential software development tools and resources to integrate NuLink Agent functionality into their applications. | [0.5.6](/resources/release_notes/notes_agent_sdk) | Yes              |
| [**`NuLink SDK`**](https://github.com/NuLink-network/nulink-sdk/tree/crosschain) | The NuLink SDK is a robust and comprehensive software development kit designed to provide developers with a wide range of capabilities.                           | [0.5.0](/resources/release_notes/notes_sdk)       | Yes              |

## For DApp Users In Demand Side

| **Project**                                            | **Description**                                                                                                                                                                                                                                                                                                                                                                      | **Current Version**                           | **Open Sourced** |
| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------- | ---------------- |
| [**`NuLink Agent`**](https://agent.testnet.nulink.org) | NuLink Agent is a web-based digital wallet that facilitates seamless communication and interaction between the NuLink network and applications.                                                                                                                                                                                                                                      | [0.5.1](/resources/release_notes/notes_agent) | No               |
| **`Demostration Dapp`**                                | The "File Transfer" Dapp serves as a third-party example, demonstrating the use of the NuLink Agent SDK to interact with the NuLink Agent. This showcase underscores the effortless integration and functionality made possible by the NuLink Application Layer, empowering developers to harness the capabilities of the NuLink network for secure file transfers and data sharing. | 0.5.0                                         | No               |


# NuLink Agent Release Notes

The current version is [0.5.1](https://agent.testnet.nulink.org/)

## v0.5.1 (2024/02/03):

1. Add storage purchase records
2. Agent UI revision
3. Fix known issues

## v0.5.0 (2023/12/22):

1. Fixed some bugs.
2. Added cross-chain support to the code logic.
3. Updated some dependency packages.
4. Updated the Nulink contract to the latest version.
5. Added batch approval functionality.

## v0.1.1 (2023/07/22):

1. Add the sequence number display of mnemonics
2. Support the Conflux network.
3. Fix transfer all amount issue

## v0.1.0 (2023/05/15):

1. Support for generating mnemonic accounts.
2. Include a QR button on the Account detail screen.
3. Default selection of the first account when unlocking Agent.
4. Displaying the current network for pending transactions.
5. Add BSC (Binance Smart Chain) as an option in the network list.
6. Enhance the user interface for private key management.


# NuLink Agent SDK Release Notes

The current version is [0.5.6](https://github.com/NuLink-network/nulink-web-agent-sdk/releases/tag/v0.5.6_4a0b66ca)

## v0.5.6 (2024/02/04):

1. Modify the upload and download process
2. Add an API to retrieve the number of backup nodes
3. Add the empty parameter validation for the API

## v0.5.0 (2023/12/22):

1. add backup node param in approve api.
2. add sendCustomTransaction api.
3. fix login api bug.
4. fixed several known issues.

## v0.2.0 (2023/07/24):

1. Add support for multiple networks.
2. Include batch approval function and corresponding API: batchApprove.
3. Add new APIs: getNetWorkChainId, setNetWorkChainId.
4. Fix login detection errors.
5. Resolve other persistent bugs.

## v0.1.1 (2023/05/15):

1. Introduce functions for connecting, uploading, approving, applying, and downloading files.
2. Resolve configuration issues related to Agent web address.
3. Provide interfaces for obtaining file lists, file details, lists of applied files, and approved files.
4. Include authentication information in backend interface requests.
5. Address known bugs and implemented necessary modification


# NuLink SDK Release Notes

The current version is [0.5.0](https://github.com/NuLink-network/nulink-sdk/releases/tag/v0.5.0_9e77a59)

## v0.5.0 (2023/12/20):

1. Fixed some SDK interface bugs
2. Added cross-chain logic support to the SDK
3. Optimized some SDK interface logic
4. Updated some dependency packages
5. Updated the Nulink contract to the latest version
6. Added batch approval functionality to the SDK

## v0.1.0 (2023/07/22):

1. Add batch approval for file requests.
2. Port IPFS service access to the backend.
3. Add support for multiple networks.
4. Support the Conflux network.

## v0.0.6 (2023/05/15):

1. Initial release of NuLink SDK.
2. Added support for secure file transfer and data sharing.
3. Integrated NuLink proxy for seamless application layer integration.
4. Enabled encrypted uploads, private sharing, and user-specified downloads.
5. Improved documentation and code examples for simplified third-party application integration.
6. Integrated NuLink network for enhanced security and decentralization.
7. Incorporated NuLink smart contract integration for secure and transparent data sharing.


# NuLink Worker Release Notes

The current version is [0.5.0](https://github.com/NuLink-network/nulink-core/releases/tag/v0.5.0_d98e1de)

## v0.5.0（2023/12/20）

1. Update the nulink contract to the latest version
2. Power the latest nulink contract
3. Fix some bugs
4. Added support for nodes that only use one set of main chains when cross-chaining
5. Added support for conflux test network

## v0.2.0(2022/10/20)

1. Add the version check mechanism [#7](https://github.com/NuLink-network/nulink-core/pull/7)
2. Repair the worker node selection algorithm and add a backup plan
3. Repair the bonding auto-failure issue
4. Repair the collected cfrag not enough issue [#9](https://github.com/NuLink-network/nulink-core/pull/9) [#10](https://github.com/NuLink-network/nulink-core/issues/10)
5. Add the concurrent mechanism in the cfrag request. [#10](https://github.com/NuLink-network/nulink-core/issues/10) [#11](https://github.com/NuLink-network/nulink-core/pull/11)

## v0.1.0(2022/9/15)

1. Release the docker image of worker node
2. Release the python installation package
3. Deploy the test network Horus constructed by worker node
4. Repair the transaction estimation error using web3 library [#1](https://github.com/NuLink-network/nulink-core/issues/1)
5. Fix the node reboot mechanism [#2](https://github.com/NuLink-network/nulink-core/issues/2) [#4](https://github.com/NuLink-network/nulink-core/issues/4)
6. Support the Windows support keystore file path


# NuLink Dashboard Release Notes

The current version is [v0.5.0](https://dashboard.testnet.nulink.org/)

## v0.5.0(2023/12/26)

### 1. Staker Management:

* Stake and unstake functionalities have been implemented to allow users to easily manage their staking activities.
* Bond and unbond features are now available, providing flexibility in staking operations.
* Monitor the status of nodes directly from the dashboard for enhanced control and visibility.

### 2. Staking Rewards Statistics:

* Comprehensive statistics for the entire network's staking rewards are now accessible, including detailed information on reward distribution.
* Stakers' details are readily available, providing insights into individual staking activities and contributions to the network.

### 3. Service Bonus Statistics:

* The dashboard now includes statistics on the whole network's service bonus, along with a breakdown of its distribution.

### 4. Testnet Faucet and Metamask Support:

* Access to the testnet faucet has been integrated into the dashboard for convenient claiming of test tokens.
* Seamless support for Metamask has been added, enhancing the user experience for interacting with the dashboard.


# Frequently Asked Questions

## General

**Q: What is NuLink?**\
NuLink network is a decentralized solution for privacy-preserving applications developers to implement best practices and best of breed security and privacy. The NuLink network provides endpoint encryption and cryptographic access control. Sensitive user data can be securely shared from any user platform to cloud or decentralized storage and access to that data is granted automatically by policy in Proxy Re-Encryption or Attribute-Based Encryption. For the data user on the other side, Zero-Knowledge Proof can help them verify the data source. In more advanced privacy-preserving use cases, NuLink uses Fully Homomorphic Encryption to customize enterprise-level data computation services.

**Q: What problems does NuLink solve and how?**\
Today it is complicated(sometimes expensive) to implement security and encryption of personal data. NuLink want to offer an out of box encryption solution that makes it easy to implement best practice, modern and up to data security. The solution will offer everything needed including data encryption, key and storage management, inter-blockchain deployment and much more.

**Q: How is NuLink different from other privacy networks?**\
NuLink network is an algorithm-based solution to protect the privacy data. We provide a combination of cryptography technologies(such as PRE, IBE/ABE, ZKP, FHE) to solve 3 parts of privacy data issues: data availability, privacy data sharing, and privacy data computing.

## NuLink Product

**Q: What is the difference between NuLink Agent, NuLink Agent SDK and NuLink SDK?**

The NuLink Applicaiton Layer consists of three main components: NuLink Agent, NuLink Agent SDK, and NuLink SDK. Here's a summary of their differences:

* NuLink Agent: NuLink Agent is a web-based digital wallet that acts as an intermediary between applications and the NuLink network. Its primary function is to facilitate seamless communication and interaction between the two. It relays requests and responses between applications and the underlying layers of the NuLink network. Users can use NuLink Agent to securely manage their digital assets and perform transactions on the NuLink network.
* NuLink Agent SDK:The NuLink Agent SDK is a set of software development tools and resources provided to developers. It empowers developers to integrate the functionality of NuLink Agent into their own applications. By using the NuLink Agent SDK, developers can enable secure and efficient communication with the NuLink network within their applications. It allows developers to leverage the capabilities of NuLink Agent, such as managing digital assets and performing transactions, while customizing the user experience according to their application's requirements.
* NuLink SDK: The NuLink SDK is a comprehensive software development kit that offers developers a wide range of capabilities. It allows developers to establish flexible connections with the NuLink network and interact with it seamlessly. The NuLink SDK provides advanced cryptographic operations and functionalities, enabling developers to leverage the full potential of the NuLink ecosystem. It allows developers to build applications that ensure enhanced security and privacy through the utilization of advanced cryptographic techniques. It's important to note that the NuLink Agent is implemented using the NuLink SDK, meaning that the Agent harnesses the powerful features of the NuLink SDK to facilitate secure communication and interaction between applications and the NuLink network.

In summary, NuLink Agent is the web-based digital wallet that facilitates communication with the NuLink network, NuLink Agent SDK provides tools for developers to integrate NuLink Agent functionality into their applications, and NuLink SDK is a comprehensive toolkit that enables developers to establish flexible connections, perform cryptographic operations, and interact with the NuLink network.

**Q: I am a Dapp developer, how can I integrate NuLink Agent into my Dapp?**

To integrate NuLink Agent into your Dapp, you can follow these steps:

* Install NuLink Agent SDK: Start by installing the NuLink Agent SDK in your project. You can refer to the [documentation](/products/dapp_builders/agent_sdk) provided with the SDK for detailed installation instructions specific to your development environment.
* Import NuLink Agent SDK: Once the SDK is installed, import the necessary modules or libraries into your Dapp project. This will provide you with the tools and resources needed to interact with NuLink Agent.
* Set up NuLink Agent connection: Use the SDK to establish a connection between your Dapp and NuLink Agent. This connection will allow you to send requests and receive responses from the NuLink network.
* Implement callback functions: In order to handle responses and execute actions after the corresponding methods are successfully executed, you can define and implement callback functions. The NuLink Agent SDK provides a list of supported callback functions that you can use.

By integrating the NuLink Agent SDK and implementing the appropriate callback functions, you can seamlessly integrate NuLink Agent functionality into your Dapp and enable secure and efficient communication with the NuLink network.

## Horus Testnet

**Q: Is Horus testnet a blockchain ?**\
No, Horus testnet is an independent network which deployed in BNB testnet. It includes five parts: a cryptographic service provider network constructed by many worker nodes; a bundle of smart contracts in BNB testnet which used to incentive the worker nodes; a Dapp for user to manage his worker nodes and interact with the smart contracts; an agent to handle the local cryptographic operations; a Dapp for user to deal with the privacy file sharing service provided by the worker nodes.


