# NxtFi Blockchain

Check out our guides and examples to integrate with NxtFi Blockchain

## What is NxtFi?

NxtFi is a third-generation, private (Proof of Authority) blockchain with integrations and API-based solutions that facilitate adoption, implementation and scalability. It is designed with a special focus on traditional businesses and institutions to update their digital services with efficient, secure and transparent transactions.

## Introduction

NxtFi is a decentralized system that provides a unique combination of features. It does not require proof of work.

Instead, it uses a Proof of Authority consensus mechanism achieved through encryption key-pair permissions, best-in-class encryption algorithms, transparent distributed ledger technology with fast transactions and low latency, and infinite possibilities through Smart Contracts implementation within a cryptographic authority hierarchy (similar to web SSL certificates). This enables a secure and robust framework for backend and storage with no fees or transaction gas.

### Smart contract within NxtFi:

NxtFi blockchain introduces a fully programmable Smart Contract structure with a powerful Javascript interpreter within, enabling blocks to have executable code written with JS logic into their body. It is also complemented with embedded functions that make data storage possible, making its architecture an easy-to-use, safe, and tamper-proof framework to host backend logic.&#x20;

Managed and requested through API https calls, NxtFi offers a robust ecosystem to host many types of apps.

## Documentación

This documentation complements the [NxtFi Whitepaper](https://whitepaper.nxtfi.org/) and is intended as a guide for developers who want to implement a solution connected to the NxtFi blockchain.


# Testing Network

Genesis is an experimental network where developers can test, create or modify smart contracts whilst monitoring the performance of the blockchain network.

## Active nodes&#x20;

At the moment there is only one active Test Node:&#x20;

[https://test-001-node.cloud.nxtfi.org/v2](https://test-001-node.cloud.nxtfi.org/v2/playground/index.html)

In the [Blockchain API Interactions](/blockchain-api-interactions) section you can find the details of the available functionalities.


# Block Viewer

Each active node has a blockchain explorer that allows users to visualize each block on the chain and its content.

The URLs of the Testnet viewers are made up as follows: `https://test-<NODE>-node.cloud.nxtfi.org/v2/visor/index.html?scope=<SCOPE>` were `<NODE>` corresponds to the available node number: `001`, `002`... `010` and `<SCOPE>` the string name of the current scope

For example, to display node 001 and "DATA" scope the corresponding URL is:

<https://test-001-node.cloud.nxtfi.org/v2/visor/index.html?scope=DATA>

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


# Playground

Playground is a Genesis network utility that allows users to interact with the blockchain. Users can review the content of each block, insert new blocks, and generate private and public keys.

Total blockchain power in a user-friendly interface. Here, you can test your Smart Contract logic with a quick and powerful tool. Check the [authentication](/authentication) section for permissions and the [Smart Contract](/smart-contracts) section for usage information.

{% embed url="<https://censo2-brasil-node.cloud.nxtfi.tech/v2/playground/index.html>" %}

<figure><img src="/files/JBuXbF4Mxr7HwfikXRnR" alt=""><figcaption><p>Playground V2</p></figcaption></figure>


# Authentication

Proof of Authority as an authentication hierarchy tree. Starting at the 'ROOT' genesis block.

To obtain write privileges to interact with the NxtFi blockchain, each user/entity must generate a key pair using the RSA-PSS specification.

After the key-pair generation process is successful, according to the Proof-of-Authority mechanism, every PubKey needs to be approved by a higher hierarchy authenticated key-pair before it can interact with NxtFi in any way.&#x20;

Higher hierarchy key-pairs can only grant or revoke permissions, and are like parent elements. However, they will never be able to sign on behalf of other key-pairs.

{% hint style="info" %}
**IMPORTANT**: To write new blocks on TestNet blockchain either through playground or directly with the API, an administrator must first register your public key and release the necessary permissions.&#x20;
{% endhint %}

## Key-pair generation

The generation of a public-private key pair is done as follows in Javascript:

{% tabs %}
{% tab title="Javascript" %}

```javascript
window.crypto.subtle.generateKey(
    {
        name: "RSA-PSS",
        modulusLength: 2048, //can be 1024, 2048, or 4096
        publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
        hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
    },
    false, //whether the key is extractable (i.e. can be used in exportKey)
    ["sign", "verify"] //can be any combination of "sign" and "verify"
)
.then(function(key){
    //returns a keypair object
    console.log(key);
    console.log(key.publicKey);
    console.log(key.privateKey);
})
.catch(function(err){
    console.error(err);
}); 
```

{% endtab %}
{% endtabs %}

## Request permission for your key

Currently, authorization for new keys is done manually. Please contact the[ NxtFi administrator](https://nxtfi.org/nxtfi-hub/) to request the necessary permissions to write new blocks.


# Create New Block

Here you will find the description on how new blocks structure should be configured

{% hint style="info" %}
**IMPORTANT:** To write new blocks on the blockchain, an administrator must first register a public key and thus obtain the necessary permissions, please see the [Authentication](/authentication) section.
{% endhint %}

### Requirements

* Read the height and hash of the last block of the scope. [See example here](/api-reference/get-the-last-block).
* Authorized key-pair. [See Authentication](/authentication).

<div data-full-width="true"><figure><img src="/files/QkmNoOIIDMB8NN8HDR35" alt=""><figcaption></figcaption></figure></div>

## Build a new block

The following data is required to build a new block:

* `prevHash`: Hash of the last block of the scope
* `height`: Height of the last block of the scope + 1
* `version`: API version, at the time of writing this documentation is `2`
* `data`: Block content: Any type. will be stringified as default.
* `timestamp`: Tiemstamp in Unix format
* `scope`:Name of the scope in which to write. This could be signer, child, or Smart Contract hash (soon to be SC alias).
* `by`: Name of the authorized signer. Owner of the key-pair used to sign
* `signature`: Block signature
* `hash`: Hash of the new block

To obtain the last two fields, it is necessary to go through a process to sign and generate the hash of the new block, which is explained below.

{% hint style="info" %}
The procedures explained below can be safely executed through the implementation of our [official libraries](/blockchain-libraries/javascript-createblock).
{% endhint %}

## Sign a block

The signature of a new block is generated using a cryptographic tool that generates a hash based on the RSA-PSS algorithm.&#x20;

The data used to generate the signature is an object that contains the following information:

`{ prevHash, height, version, data, timestamp, by, scope }`

**Example:**

{% code overflow="wrap" %}

```javascript
let blockToSign = {
    prevHash: "bd125e337f0cc7782b0e3465157b60535151362220f490650bed6b4be69bbb4b",
    height: 14,
    version: 2,
    data: "Hello World!",
    timestamp: 1669768443723,
    scope: "DATA"
};

const algorithmParameters = {
    name: "RSA-PSS",
    saltLength: 32,
};

let signature0 = await subtle.sign(
    algorithmParameters,
    await getPrivateKey(),
    Buffer.from(JSON.stringify(blockToSign, null, 2))
);
let signature = Buffer.from(signature0).toString("base64");
```

{% endcode %}

## Generate a new hash

Once you have the signature of the block, you must generate the new hash using the SHA-256 cryptographic algorithm.&#x20;

The data used to generate the hash is an object that contains the following information:

`{prevHash, height, version, data, timestamp, by, scope, signature }`

**Example:**

{% code overflow="wrap" %}

```javascript
const blockToHash = { 
    prevHash: "bd125e337f0cc7782b0e3465157b60535151362220f490650bed6b4be69bbb4b", 
    height: 14, 
    version: 2, 
    data: "Hello World!", 
    timestamp: 1669768443723, 
    by: "DATA",
    scope: "DATA",
    signature: "WQJFA6B1cr8jZqGu08fh/LHk41nWif4Qun+2g1eIrrE8/l3WxSiSFicM86YLqCWwtFVQ+i5j8wsY8BfrxE4Cz/6Mc8FXOsUgYKdUzIKC5Og0+PgwlJOSLIaazNHS/4ypKExcIatB1dpQKU4Y5e+ozytQIM/i5E4tPbPTzP3avVYfnsAutINpGKcvhW6+6A8FUWH90OmeOpXE+c7OQb400z4BlCCQWE7rYnxSM4gUCJBuJ1T5ABm7/JfdGffNk+5xThe1NBVu7WEo85OhMMOFpOm48k9q53At1pAduJaTuO1IYU5qXfmQJa5w5tm7MLmOsC0mGJVY/PoRDQ9/K/xu/g==",
}
let hash256 = crypto.createHash("sha256");
const data = hash256.update(JSON.stringify(blockToHash));
let hash = data.digest("hex");
```

{% endcode %}


# Blockchain Libraries

This library introduces tested code to easily configure the Sign and Submit process, along with Confirm block propagation functions that can be imported into your app to make it executable on NxtFi.

{% content-ref url="/pages/Q8mnl48uFLWR6fyIn7lp" %}
[Javascript - CreateBlock](/blockchain-libraries/javascript-createblock)
{% endcontent-ref %}


# NxtFi Tools


# Javascript - CreateBlock

It is a JavaScript library created to generate and send blocks to the NxtFi blockchain according to the network specifications.

## NPM Library URL

### Library for backend developments interactions

{% embed url="<https://www.npmjs.com/package/@guerrerocarlos/blockchainlib>" %}

## ENV Variable

Define the blockchain endpoint to use as an ENV variable:

```
export BLOCKCHAIN_ENDPOINT=https://test-001-node.cloud.nxtfi.org/v2
```

## Integrated module functions

## clientSign

This function is used to obtain the signed block that will be sent to the blockchain in the `submitBlock` function.

#### Parameters:

* SIGNER (Entity, name of authorized pubKey)
* SCOPE (Signer, Child scope, or SC hash)
* BLOCK CONTENT
* PATH TO PRIVATE KEY

Return => signedBlock.

## submitBlock

This function is used to send the signed block and register it on the blockchain.

#### Parameters

* SIGNED BLOCK

Return => result.data

## confirmBlock

This function is used to confirm submitted blocks and check whether they have been propagated successfully or not. It continuously checks for a maximum of 10 seconds or until finalization time is achieved.

#### Parameters

* HASH (submitted block hash)
* i (Optional. Seconds to reduce tolerance from default 10sec)<br>

Return => result.data


# Smart Contracts

A particular block body data structure with special instructions to be executed.

## Compute power.

Regardless of the implementation, any block where the 'blockContent' property starts with `//` is interpreted as a smart contracts and its content will be executed with a JavaScript interpreter. All smart contracts must start with a comment on the first line as shown below:&#x20;

`// <DESCRIPTION?>  || <CONTRACT_INVOCATION(HASH/ALIAS)`

When declaring a smart contract, this line is commonly used to provide a description or version information. However, when invoking a smart contract, this line must be filled with either the contract hash or the contract alias, if it has been set previously.&#x20;

### The scope

A core concept within NxtFi, the scope is regarded as a branch of the tree-like framework architecture. It is an essential component of the hierarchical structure that empowers the network's most robust features. In its simplest and most practical form, the scope is defined as the pathway to the organization of the smart contracts domain. It serves as a directory to organize code, state, and their interactions. But they are not arbitrary in every sense, meaning that a scope is either the name of the entity who is signing, or a contract hash identifier, or even a child entity authorized by its parent through the `grantWrite` authorization process.

### Usage

The first stage when declaring a smart contract involves following simple syntax rules. As mentioned earlier, it is mandatory to begin with a commented headline. Following that, the execution logic needs to be implemented. This includes:

* Inputting Parameter and Variable declarations (JSON inputs are allowed to interact with SC).
* Access Control Layer system middleware (ACL to hide sensitive data or to serve data directly from an API).
* Smart Contract code logic.
* Smart Contract Alias setters (directly set a SC alias in deploy to initialize a custom/dedicated scope).

The code will be executed every time the smart contract is invoked, in a synchronous loop. It is important to consider the initial execution (when the SC is deployed for the first time) and handle all possible exceptions to prevent crash faults.

Whenever the execution thread is blocked due to an asynchronous call, a crash fault, or an infinite loop, the interpreter is not able to distinguish between them. Consequently, the code will be executed again until the code resolves or a specific time interval (δ) has elapsed. Therefore, it is important to be cautious and avoid infinite loops, as they can cause the block to fail.

### Smart contract Call

After declaring and propagating (deploy) a smart contract code block on the NxtFi blockchain, it becomes ready for usage and execution. As mentioned earlier, you can choose to use either the contract hash identifier or the alias label, depending on the specific use case. However, it is highly recommended to use the alias label right from the beginning. (if it was not immediately configured in SC deploy)&#x20;

As this field will become the scope of its implementation. Every piece of state associated with the smart contract will be tracked and stored using the scope route. In other words using the label will enable the possibility to upgrade the code without loosing the connection to smart contract data.

### Alias

Aliases are utilized to offer a concise and user-friendly representation of a smart contract hash identifier. They also provide the capability to link different versions of smart contracts within a single route, enabling orthogonal persistence throughout smart contract code upgrades.&#x20;

Essentially, an alias is a label that points to a specific memory allocation, which hosts data and Smart Contract's Code instructions in different slots but still referenced between each other.

So Code can be upgraded by re-deploying a new version in that allocation. It is important to notice that every time a new SC is deployed in a specific allocation (triggered by the `setAlias()` function), the system will keep track of every encrypted block hash that was executed, represented in a registry list.

The alias must be set before making any state changes. To accomplish this, a block needs to be propagated with the appropriate embedded function specifically designed for this purpose (the `setAlias()` function). The Alias result has this structure: `<entity>__<name>` (Refer to the [functions](#embedded-functions) section for usage details.)

### Parameters

When a Smart Contract requires inputs to delivery some special functionality, they must be declared as a strigifyable object literal.&#x20;

Each smart contract can receive parameters as one object. The syntax for delimiting these attributes is achieved with the commands `//INPUT` and `//INPUT END`, as shown below:

```javascript
const input =
// INPUT
{
    to: "",
    amount: 0,
};
// INPUT END
```

### Embedded functions

The functions described below work as a two way communication channel between the instructions written in the submitted Smart Contract, the invoked Smart Contract( if is the case) and the NxtFi storage system.&#x20;

By default when a  block body goes through the NxtFi virtual machine, the execution logic will check if the declared scope in the functions comply the `'alias'` syntax (see '[Alias](#alias)'),  if it doesn't this field will be automatically filled with the imported contract hash or the block hash(see [SC environment variables ](#smart-contract-environment-available-variables)below)

<table><thead><tr><th width="477.5">Function</th><th>Description</th></tr></thead><tbody><tr><td><code>put({ name: string, value: &#x3C;any> })</code></td><td>PUT Key/Value storage</td></tr><tr><td><code>get({ name: string})</code></td><td>GET Key/Value storage</td></tr><tr><td><code>gettrace({ path: string, scope?: string, options?:{object}})</code></td><td>GET Storage system Trace logs. allow same options &#x3C;obj> as list</td></tr><tr><td><code>list({ name: string, scope?: string, options?:{maxkeys?: int, startafter?: string, raw?: boolean&#x3C;default=false>})</code></td><td>List existing keys and directories</td></tr><tr><td><code>del({name: string})</code></td><td>Delete one key/dir</td></tr><tr><td><code>delMany({prefix: string, options?: &#x3C;list-opt-object>})</code></td><td>Delete all keys that match</td></tr><tr><td><code>grantKey({name:String, pubKey:String, permissions?:Object{canGrant:Boolean, maxGrantLimit:Number, expiration: Timestamp }})</code></td><td>Authorize child key-pair</td></tr><tr><td><code>revokeKey({name: String})</code></td><td>Revoke child key-pair</td></tr><tr><td><code>log({ properties: &#x3C;Computable Variables>, optional?: "key/pair" })</code></td><td>describe logs in block body</td></tr><tr><td><code>result({ message: &#x3C;Computable variables> })</code></td><td>display computable results </td></tr><tr><td><code>persistArchive({ name: &#x3C;fileName string-with-extension>, fileHash: &#x3C;FILE_HASH>, data: &#x3C;custom-metadata any-type>})</code></td><td>persist temporary uploaded files to permanent storage.</td></tr><tr><td><code>setAlias({scope?: String, name: String&#x3C;identifier>, value: &#x3C;contract-hash-pointing-to> })</code></td><td>configure alias name to any smart contract hash. </td></tr></tbody></table>

### Smart Contract Environment available variables

To enhance the coding experience and increase the functionality of smart contracts, there are two distinct property fields that can be utilized: {block} and {contract} objects. These objects have the same structure and key names, but they refer to different blocks (if applicable).

`block.<prop>` is pointing to the current working block.

`contract.<prop>` is pointing to the invoked Smart Contract block.

For example: (current)

* `block.prevhash` = hash of the last block of the scope
* `block.height`  = height of the current block.
* `block.data` = data field of the current block.
* `block.scope` = current block scope name
* `block.timeStamp` = current block time-stamp
* `block.by` = Signer - entity
* `block.version` = API version number
* `block.signature` = current block signature
* `block.hash` = hash of the imported Smart Contract

For example: (invoked)

* `contract.prevhash` = hash of the previews block of the invoked SC
* `contract.height`  = height of the SC block.
* `contract.data` = data field of the SC block. (code to be executed)
* `contract.scope` = SC block scope name(usually the entity who wrote the code)
* `contract.timeStamp` = SC block time-stamp
* `contract.by` = SC Signer
* `contract.version` = API version number
* `contract.signature` = SC block signature
* `contract.hash` = hash of the imported Smart Contract

### **Example of a block declaring a smart contract:**

Using different embedded functions.

<pre class="language-javascript"><code class="lang-javascript">// Example Smart Contract store person data

var input =
// INPUT
{
    id: "",
    name: "",
    email: "",
};
// INPUT END

<strong>put({  
</strong>    name: path/to/input.id, 
    value: input  //input object
});

grantKey({
  name: "NAME",
  pubKey: "-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwvCkzqn0vOYRzZFAlh2OeqbaEjLe/VsJUv5YWmKDnDNG2+DPQckaf6pq++Ygy8P6/0LHzLVizbYAzf48brzY3K21kwxWsCNVVl1utEXo0yHLJu9YWdfLJSjE4PUhAAxbKOZFSHwBz6kM6aNT8BSpqFL6TcUbSPCTkygmJP5Y94aRp2lZU7NBoA/QpnYpiVbOf4UaRpwMsxlWAbsqLNGxO+5Rh/mFfNHjW4mG04Sx7a2404ZCBPAIkZwJkLNOuWYH2Ez+W0VEmcF8pMbqtE6hmDDzJvtneKq+ueeXFsiZ1NmGHwfn0VCEPrUdpFIVizEoJZIz8JA9tkjZ+ZVPBfYlBQIDAQAB -----END PUBLIC KEY-----",
  permissions: {
    canGrant: true,
  }
});

const foo = get({ name: "path/to/id"});  //resolve as input object

log({ properties: "Log message", bar: foo });

del({ name: "path/to/id" });

setAlias({ name: "NAME", value: "SMART-CONTRACT-HASH" });

const idArrayList = list({
  name: "path/to/",
  scope?: "A-SCOPE",// optional, by default scope property will be populated with alias.
  options: {
    maxkeys?: int,      // optional  
    startafter?: string,   // optional  
    raw?: boolean&#x3C;default=false>   // optional  
  }
});

// track list is an array of timestamps records of file storage modifications.

const trackList = gettrace({
  path: "path/to/id",
  scope: "A-SCOPE",
  options: {} // same list option obj
});

result({ message: "Smart Contract Result" + block.hash + "by =" +  block.by });




</code></pre>

### Example of  a block invoking a smart contract

Invoke a smart contract using alias nomenclature.

System only accepts JSON objects as inputs.

```javascript
// Entity/alias__NAME  || smart-contract-hash


{
  "id": "invoking-entity__alias",
  "name": "Input/to/trigger/functionality",
  "email": "hello@world.com",
  "pass": "store-private"
}





```


# The Storage System

Managing state within NxtFi

A key feature of the NxtFi blockchain framework, in addition to its computational power, is its ability to store data content and state. In this article, we will provide an overview of its architecture.

The NxtFi framework supports various types of data storage, but different functions are available for implementing CRUD operations. We can distinguish two major paths. First, for data content that can be serialized as a JSON object, no additional considerations are required. It can simply be placed within the block body content using the embedded functions. Read, update, and delete actions can also be performed on this data.

On the other hand, other files are also accepted and can be stored within the framework. However, they follow a different path and require additional validation and configuration. In the following section, we will outline the necessary considerations and explain how file uploads work.

As of this version of the documentation, the NxtFi framework accepts files of any type up to a size limit of 10MB.

Regardless of the data type, every interaction with the storage system must be done through an HTTPS call. For syntax information, please refer to the [API-listing](/api-listing-files) section. To understand how to retrieve a file from storage, refer to the endpoint usage in the '[get file from storage](/api-reference/get-files-from-storage-by-scope)' section. Additionally, the '[storage tracking](/api-reference/storage-tracking-timestamp-block-info)' section provides information on tracing connections between the storage system and the blockchain.


# Upload Media Files

Overview on how to configure a client for media files uploads

Configuring a client to access the file storage service from the NxtFi API requires specific knowledge. Since the operation needs to be securely recorded in the blockchain without compromising computational power, certain actions must be taken on the client side to achieve this objective. The steps described below guarantee a fully transparent and efficient mechanism for uploading files up to 10 MB in size each.

Is good to remember that the client will need:

1. Obtain the necessary client credentials: Acquire the required credentials, such as authorized key-pair from the NxtFi API to authenticate the client.
2. Establish a secure connection: Configure the client to establish a secure connection with the NxtFi API endpoint using HTTPS.
3. Prepare the file for upload: Prior to uploading the file, ensure that it is properly prepared. This may involve validating the file format, checking for any restrictions on file types, and compressing the file if necessary. (At the moment any type is accepted up to 10MB for each call)

## Steps to upload file

<figure><img src="/files/1WUy8fGVoEvFfauyEwgB" alt=""><figcaption></figcaption></figure>

### 1 - Request Upload URL

The first step after checking content-type and size is to request a pre signed url to upload the file. A JWT signature is going to be required in order to confirm that who signed the request and upload the file to the temporary staging area is in possession of authorized keys with write permissions in NxtFi API

* Generate a SHA-256 Hash from the file.
* Build the JWT signature using the JOSE library as described below:

```javascript
  by = by.toLowerCase(); // the entity owner of the private key.
  const alg = "RS256";
  const pkcs8priv = pemPriv; //example: "-----BEGIN RSA PRIVATE KEY-----MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCMWdzSQfk5eznBFCb0mCYVwpBSaKx7UW0K1Mx3TJ479wdJ0eLGOYqdBnDuS7xs7d+PYhaDxKA/IIAOxcVkRHq4/m26RQ4btbr6OY7zS5pc7CYPcTwJW2b8a4gca1rjsw7Ziv4qDTp8LwawvlVcfap1vfAvjGAIdbOOC6rSoSn8pVtJqyAVbzBY3ggGfY7fP62cDMfBV6Hp/ZH3OPfR5vhZd1G/WcBrtWMOk5p7kgvAVpF60ysS9xspKxgq7Uw3nsruwa2zMIpIeXlFBUmAEp6hiwsNwInoMNQ+jpJPKPWhLo3vvCH9ZAWVZ0yZbGgSDC80I56m3RjYHwVkvNeg4SUNAgMBAAECggEARKSqyLb1orRvAczOZLCJZ/kZxwRk34dqknKTcgGqHl/qU6Nwi0yXS8dbsmCeTpRk0+bAZj/jtBw8JX161lhbwWDG3+RoSwst4LYIAVxHqgzhbIoQN+9ZRjl9f5DOCjGIIMPHHWAM67HATu84Jp1bomx8LXU1fs26PM3eBVhHhcXMl929eoWe+BIKtUir5qqYhPF8Oq1eLW2qO8i+9vhicwUeHn3MFZjR8Ty2F4mJenaN90Ek/1tpvLM8Cu8j/Yfj0heBuHhBdXTC4LCNqvfZj+MdK/L7XOxaE+UvV80jHgzTalxKBRHyNzzeBAoSagCkLQFX1Td3kznisQXLuJFiTQKBgQDAyJZoboKxnFr/f/DqUiKOFkFbA2+i8zoZPmqeDtGiwfbugVUBVRAG5eRq1LAUtAXlNC9DN9NqgzjxmAmVa9MN/6myivjg3tZNifP4j/dq8dO7D6BnRUkkhRXuTodKxZ8ScdjaTRqOHKrGBDcd5Qb94NgQ8SrpoKphW1Tm4DOFXwKBgQC6X8X/PEJ6CujwNAj2oOq/w9Hie0SQVTFCq/zJqLNC7GmPc8ET8dwQqNW4PVs+eUtbuxo8VgldaMBhEUtwWO5ZkhfUsWgJyIjR3jKwpbB6eaoHrhCdUF0wE/OH/Cezur5H+b/AeD57ix0DCpzuMxkHx/ATCVTDzAelXP/qL0MhEwKBgBPxrH3JUQQG5PMhzU6wiJqieshrppT5DL2n02feqJlp753lC2JD5pCQH/1dW4oIxcNcjrcpg1m1kaKM1BD9QqxkEq5B6lV5ODp1VyQT4MjTk8/6YeHNLS/2BLrOrPhzUW2bEZAkAedJ1/D8ZqdVFlAVfsTh7kqVMIs546Ku9yWJAoGAY75R9tFHOo2QMM2IZoWkXNDuCOmzvhL59BabiUlR9uUTcYSfto7gGcJh7uJXbM35eLRfzB63kFg5bTmWSCAwH5vCSUBQz7uVDcx/EG78Te/DAa00kxypYsuqsAJRNS0iHN8asmUn+3JuKmyJpCmQocttPqLlzIvrI6LsC2cT5CUCgYBLuWHHn0Mf+Vn5jdncAdh5FWj3K/IlVLDCUAXp+dJ4IGgd2QxxwHqz4HT1/VHdp9nERFiK7lXD9yYEfYFtrsc3DGF9Ic3J8FWf0DNbnBc8mIgBtEXeYOMdJTuIiOH+3c/pMuWhbMI6gmpKcR0y6W5lQUg0qBExphG8YabXHga/OA==-----END RSA PRIVATE KEY-----"
  
  const privateKey = await jose.importPKCS8(pkcs8priv, alg);

  const jwt = await new jose.SignJWT({ by: by, fileHash: fileHash, fileSize: sizeInBytes })
      .setProtectedHeader({ alg })
      .setIssuedAt()
      .setExpirationTime("24h") 
      .sign(privateKey);
```

{% hint style="info" %}
Files reaching staging area will have a life-cycle until complete deletion of 24hrs. Avoid changing the `setExpirationTime()` property to prevent uncaught exceptions.
{% endhint %}

#### Send the PUT request to `/newfile` endpoint.

#### &#x20;(See [Presign URL request](/api-reference/presign-media-file-upload) for call details)

### 2 - Upload File to staging area

After receiving the success response from the PUT call to /newfile, the content can be uploaded to the provided URL using the response fields as template call fields. In this context, we will describe the implementation of the POST method using the FormData browser API.

```javascript
//create a formData

 const formData = new FormData();
    formData.append("acl", "public-read"); //condition outside response to add
    Object.entries(response.fields).forEach(([k, v]) => {
      formData.append(k, v);
    });
//append file as the last element of the formDaata to avoid uncaught exceptions.
    formData.append("file", fileContent);

```

#### Perform POST call

```javascript
// POST req to received url
fetch(response.url, {
      method: "POST",
      body: formData,
    })
    .then((res) => {
        if (res.ok) console.log("FILE successfully loaded");
        }
        // res code status 204 indicates succesfull upload

```

\
Once a file is successfully uploaded, it will be temporarily stored in a staging folder while waiting for persistence. This staging folder serves as an intermediate storage location before the file is permanently stored. However, files in the staging folder have a maximum duration of 24 hours.

To ensure the file's long-term persistence, a block must be signed by the same entity who uploaded the file. By propagating a blockchain-confirmed block, its storage and availability are guaranteed.

If the file is not persisted within the 24-hour timeframe, it will be permanently deleted from the staging folder. This mechanism ensures that only files persisted in blocks are permanently stored.

### 3 - Send a new block to persist the file

Use the custom function `persistArchive` to ensure file long-term and proper path generation. A optional `data` field is available to add custom metadata to the file block registration

```javascript
persistArchive({ 
    name: "filename.pdf", //include file extension
    fileHash: "file-hash-string", // the fileHash used to sign JWT
    data: {YOUR-CUSTOM-DATA},  // optional property, metadata field.
});
```

### Smart Contract Result

Treated as every stored value in the NxtFi storage system, the file can be required through a `get function` at contract level:

```javascript
const responseObj = get({name: "filename"}); 
```

&#x20;or as an endpoint query call:

```
https://test-001-node.cloud.nxtfi.org/v2/_storage/<scope>/filename
```

{% hint style="info" %}
Note: When querying the result value, neither at contract level or at endpoint call the extension of the file is provided.&#x20;
{% endhint %}

&#x20; and the response object will be like this below. Will include the Url were the file is located and can be downloaded.

```json
{
  "scope": "scope",
  "name": "filename.pdf",
  "data": {
    "Nombre": "ING. Elvis Bonilla",
    "Cedula": "V-123434124"
  },
  "blockHash": "b42547cb3e698cbd1574901148551e28a3085de1c594323ecf455eb38df0e830",
  "fileHash": "73d5a33577951cfbc16638f7f6500847db10d42bba1dae9267cb126e16060e6c",
  "url": "https://nxtfi-bucket-us-east-1.s3.amazonaws.com/blockchain/v2/test-001/_archive/__<scope>/<fileHash>.<extention>"
}
```


# Blockchain API Interactions

"Communication protocol, each API interaction must adhere to the syntax described below."

### Https  calls have this structure:&#x20;

`https://<cluster>-<node>.cloud.nxtfi.org/v2/<ENDPOINT>`

#### Description:

`cluster` :  Available public option `test`

`node` : Node number i.g: `001-node`

`Endpoint` : Available public options described in the [API reference](/api-reference/get-node-health) section.

### General knowledge specification:&#x20;

As a general rule, on the NxtFi API, each HTTPS call that points towards a directory folder in the storage system must end with a forward slash /, otherwise the response will prompt:

```
{"error": "notFound"}
```

On the other hand, HTTPS calls pointing to files won't admit a forward slash at the end or the file extension. If that is the case, they will also prompt the same error message.

For example  `SUCCESS`:

<https://test-001-node.cloud.nxtfi.org/v2/\\_storage/\\><scope>/\<directory>/

<https://test-001-node.cloud.nxtfi.org/v2/\\_storage/\\><scope>/\<filename>

For example  `{"error": "notFound"}`:

<mark style="color:orange;"><https://test-001-node.cloud.nxtfi.org/v2/\\_storage/\\><scope>/\<directory></mark>

<mark style="color:orange;"><https://test-001-node.cloud.nxtfi.org/v2/\\_storage/\\><scope>/\<filename>/</mark>

<mark style="color:orange;"><https://test-001-node.cloud.nxtfi.org/v2/\\_storage/\\><scope>/\<filename>.json</mark>


# Access Control Layer

API's middleware execution context for client side requests.

A kind of Proxy layer called ACL is introduced to the framework. Now, every Smart Contract has the native power to review, limit, restrict, or redirect any endpoint request.

Data stored inside a scope might be confidential, and the need to make it private arises, at least when certain conditions are met. Alternatively, your data structures inside your NxtFi implementation may require some processing before delivery in certain actions. These are some of the use-cases that require the implementation of ACL middleware.

Having a proxy context to execute instructions before data delivery from the API is a very powerful feature. It enables privacy and protection for blocks and data storage, thus allowing for the capability to personalize responses granularly for different requests on the same endpoint.

Lets dive into this feature starting from:

* [How it works](/access-control-layer/how-it-works).
* [Syntax & Smart Contract requirements](/access-control-layer/syntax-and-smart-contract-requirements).
* [Error & exceptions handling.](broken://pages/L30dKhhzI437KBxC70QN)
* [Examples](broken://pages/sTs7QW6ofSkh7OGbDcFm)


# How it Works

This article intend to be a system overview of this feature.

The entry point of the ACL feature is the SC declaration. As the vision claims to enable the SC to have extra capabilities, the first step is to declare inside the code block that an instance of ACL is required. Having the commented line `// ACL` as top-level code is mandatory to achieve this.

Input declaration and `if(ACL)` statements are also required inside the block body to properly use this API (see [Syntax & Smart Contract requirements](/access-control-layer/syntax-and-smart-contract-requirements)).

The system will resolve the `if(ACL)`statement and any instruction inside every time a request hits the storage endpoint, or any endpoint that results in a block (i.e., "storage," "block," "timestamp," "height"), the ACL runtime is triggered.

First, the node will find the original block where the current SC is declared. After checking the existence of the `// ACL` top comment in the case of SC declarations or in the parent SC when invocation calls, execution will proceed to create a shallow copy of the original returning block.

The copied block is now ready for a morphologic reconfiguration, where, in a sandboxed environment, it will safely execute itself, looking for the condition `if (ACL)` to see if exposes any errors or throw's exceptions.

Every exception will quit the sandboxed runtime returning a custom JSON value.

This sandboxed execution will input, as a JSON object payload, the request headers, query parameter fields, path, and JWT tokens provided in it. Last but not least, the execution is done with a global variable `ACL=true`.

After all, the node enters a selection process where it verifies:

1. Original block integrity.
2. `if(ACL){}` code execution results.

**"Handle Exceptions"**

During execution, smart contract runtime exceptions are treated as ACL failures and will display the original block with dedicated messages.

Smart contract "*execution exceptions"* are handled as responses and will be separated into *"instances of Error"* or *"String-type exceptions"*.

The first ones will also be treated as ACL failures and will display the original block with dedicated messages exposing failure details.

On the other hand, String-type exceptions will be parsed back as responses and returned to the client following the instructions specified in the original block.

If this execution runs without concluding in any exceptions, the middleware functionality is passed, resulting in a normal API interaction. In other words, no exceptions during the ACL execution context mean that blocks and storage data are fully public. (see the [Examples](broken://pages/sTs7QW6ofSkh7OGbDcFm) & Usage implementations ).


# Syntax & Smart Contract requirements

How to get full advantage of the feature.

General syntax model:&#x20;

* &#x20;`// ACL` commented line. (top code recommended)
* `var input = {}:` Smart Contract object. Data structure where the requested metadat&#x61;*(headers, path, jwt, etc.)* is stored.
* `if(ACL)=>{}`statement, deploy conditions. This is the ACL-feature execution context, indeed.
* `throw` excepted output.

This are the requirements to implement successfully the ACL feature. Let's dive a bit into them just to understand the context of their implementation.

`"// ACL"` comment: new instance of ACL execution is required.

`var intput = {};` reserve memory location for self execution inputs.

`if(ACL){`

`if (path[2] === "_storage"){`

&#x20;   `res= { private:"you have no perms to            see this" };`

`sendResponse(res);`

`}else { <Smart-Contract-Logic> }`

This statement is the place to deploy every case in which the ACL should throw anything special. for example: *"this route should be private"* or *"this request should return directly data".*

*"Throw Exception"* if custom actions are required otherwise will execute a normal API request.&#x20;


# Example

In this section we will provide some implementation example as a template to use the Access Control Layer Example of Smart Contract declaration interfacing ACL request.

{% embed url="<https://gist.github.com/panch8/95aeaa2dc3739f59f9fd203a1c26b2fc>" %}

Let's Dive into details of this implementation step by step, Here's a review of the code:

* Access Control Logic:

The code starts by checking the value of ACL. If ACL is truthy, it proceeds with access control checks. Otherwise, it falls into the else block, the actual SC logic will be hosted in this else block. ACL is true when requests arrive to *storage, timestamp, height, block, and the block includes the // ACL comment.*

* Input Declaration: `var input = {};`&#x20;

Variable "input" is the object where the event properties of the request are going to be stored. is also parsed:

`input.headers;` -where to check compatibility at a header level.&#x20;

`input.path` - is going to retreive the requested path,

`input.query` - the query string params.

`input.jwt` is the location where the decoded payload of a verified jwt token is displayed. (the actual jwt signature is located raw @*input.headers.jwt*)

(only keys registered in the NxtFi blockchain are eligible to sign jwt tokens)

* Helper Functions/Statements:<br>

```javascript
function blockAccess(){
    var res = {};
    res.private="No tienes permiso para ver esta informacion";
    sendResponse(res);
}
```

It is good to mention the importance of the helper functions/statements inside in the Smart Contract's code. It enhances it's readability, thus reducing the risk of errors and improving maintainability. In the provided example: good examples of this type are:

sendRespone(resObj){ throw JSON.stringify(resObj) }

This is the function responsible of throwing the necessary exception to make ACL runtime exit in a specific way. the returned object is a general porpouse object-literal stringified as JSON string.


# API - Listing Files

Listing results on https calls

When query calls point to a directory, as mentioned in the API interaction section, they will need to be ended with a '/'.&#x20;

Getting a list of files from a directory enables optional query string specifications in order to manage and organize these lists according to the following syntax:

`https://test-001-node.cloud.nxtfi.org/v2/<ENDPOINT>/?raw=<true>&startafter=<key>&maxkeys=<number>`

## If no query string is declared, default listing is ascendent-alphabetical order.&#x20;

<mark style="color:blue;">`GET`</mark> `https://test-001-node.cloud.nxtfi.org/v2/<ENDPOINT>/?<query-string-options-and-values>`

If a query string is declared in order to be valid must have a `=` between the query name and its value

#### Query Parameters

| Name       | Type    | Description                                                                  |
| ---------- | ------- | ---------------------------------------------------------------------------- |
| raw        | Boolean | returns listed items in native structure                                     |
| startafter | String  | Return keys starting after designated value. Alphabetical order.             |
| maxkeys    | Number  | Return designated max keys values. Default and max on each query 1000 items. |

### Listing trace interaction:&#x20;

The system for monitoring interactions is listed in a slightly different way. For more information on tracing, please refer to the [Storage tracking interactions](/api-reference/storage-tracking-interactions) section.&#x20;

Interactions with the NxtFi file system are stored in tracking directories that point to a specific file. This means that a single stored value may have a list of tracking files related to its manipulation.&#x20;

Therefore, when listing the tracking information of a specific file, its query must include "/" endings as they are fixed directories to their "parent" element.

For example  `SUCCESS`:

<https://test-001-node.cloud.nxtfi.org/v2/\\_trace/\\><scope>/\<fileName>/

<https://test-001-node.cloud.nxtfi.org/v2/\\_trace/\\><scope>/\<fileName>/\<timestamp>

For example  `{"error": "notFound"}`:

<mark style="color:orange;"><https://test-001-node.cloud.nxtfi.org/v2/\\_trace/\\><scope>/\<filename></mark>

<mark style="color:orange;"><https://test-001-node.cloud.nxtfi.org/v2/\\_trace/\\><scope>/\<file>/timestamp/</mark>


# Get node health

## /health

<mark style="color:blue;">`GET`</mark> `https://test-001-node.cloud.nxtfi.org/v2/health`

Get Blockchain Node Status

{% tabs %}
{% tab title="200 " %}

```json
{
    "status":"running",
    "server":"nxtfi-node",
    "stage":"development",
    "time":1676472456516
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
To test the endpoints you can use the terminal, postman or open the link directly in the browser.
{% endhint %}

{% tabs %}
{% tab title="curl" %}
{% code overflow="wrap" %}

```bash
curl --location --request GET 'https://test-001-node.cloud.nxtfi.org/v2/health'
```

{% endcode %}
{% endtab %}
{% endtabs %}


# Get the last block

Query the last block of a scope

## /\_head/\<scope>

<mark style="color:blue;">`GET`</mark> `https://test-001-node.cloud.nxtfi.org/v2/_head/<scope>`

#### Path Parameters

| Name                                       | Type   | Description                                               |
| ------------------------------------------ | ------ | --------------------------------------------------------- |
| \<scope><mark style="color:red;">\*</mark> | string | Get information of the last block registered in the scope |

{% tabs %}
{% tab title="200: OK " %}

```json
{
    "head": "e1beda10fee6405448a84e06cb8ff7fe43dbf509a807094398297ffb24b82125",
    "height": 10,
    "timestamp": 1667134954981
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="curl" %}
{% code overflow="wrap" %}

```bash
curl --location --request GET 'https://test-001-node.cloud.nxtfi.org/v2/_head/JCOAKS'
```

{% endcode %}
{% endtab %}
{% endtabs %}


# Get block information by hash

Obtain information about a specific block by providing its hash. If its not provided, full list of hashes will be displayed.

## /\_block/\<hash>

<mark style="color:blue;">`GET`</mark> `https://test-001-node.cloud.nxtfi.org/v2/_block/<hash>`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
| hash | string | block hash  |

{% tabs %}
{% tab title="200: OK " %}

```json
{
  "prevHash": "3ca944db13730d25e880922012ad357358ff169173facc909391e17c6233d1f2",
  "height": 49,
  "version": 2,
  "data": "// HELLO",
  "timestamp": 1676471794193,
  "scope": "DATA",
  "signature": "JYMhtSOJdqxXJHi0C0EqhfRu7mFnsUmqxICVNgRZrOgj391Z0K98SzqvWKCx7GC63ms/8nzC3BklUqBpcbQGPY7UJt5x+qLFidow7s1/THb/gZw/Ukpg4zDxqa9YikmJu9HTkWPVJC8y7PwoxRkgWqTnsCgyfkJf6kuiusUMq0TGBxNEZcxkkLDvM2UFLL/PqKFQy+WqEz712QDwtY80H9s92jAbCa/frFF7hR60rCy7lLBtzLOTB14tNLeHCj5e+2931Gy6bvHlXPNowJdL7lmWXrDLYdwjMoQH7GrlizTgJXTQzK4xm6RiRrDdJnOlXICQxqE1iVC59yFLy700Ig==",
  "by": "DATA",
  "hash": "c4575a343793dde67655cfaf3b1be4dcbbf5e8a6f59d33e525a0b5004becde12",
  "": "}\n\n",
  "__cache": {}
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="curl" %}
{% code overflow="wrap" %}

```bash
curl --location --request GET 'https://test-001-node.cloud.nxtfi.org/v2/_block/c4575a343793dde67655cfaf3b1be4dcbbf5e8a6f59d33e525a0b5004becde12'
```

{% endcode %}
{% endtab %}
{% endtabs %}


# Get block information by timestamp

Obtain the information of a specific block through its timestamp. Also allow timestamp ordered block listing.

## /\_timestamp/\<timestamp>

<mark style="color:blue;">`GET`</mark> `https://test-001-node.cloud.nxtfi.org/v2/_timestamp/<timestamp>_<scope>`

Example of timestamp listing.

`https://test-001-node.cloud.nxtfi.org/v2/_timestamp/`&#x20;

#### Path Parameters

| Name      | Type   | Description                           |
| --------- | ------ | ------------------------------------- |
| timestamp | Number | timestamp of the required transaction |

{% tabs %}
{% tab title="200: OK " %}

{% endtab %}
{% endtabs %}


# Get block information by height

Obtain information of a specific block by its height.

## /\_height/\<scope>/\<height>

<mark style="color:blue;">`GET`</mark> `https://test-001-node.cloud.nxtfi.org/v2/_height/<scope>/<height>`

#### Query Parameters

| Name                                    | Type   | Description |
| --------------------------------------- | ------ | ----------- |
| scope<mark style="color:red;">\*</mark> | String |             |
| height                                  | Number |             |

{% tabs %}
{% tab title="200: OK " %}

```json
{
  "prevHash": "3ca944db13730d25e880922012ad357358ff169173facc909391e17c6233d1f2",
  "height": 49,
  "version": 2,
  "data": "// HOLA",
  "timestamp": 1676471794193,
  "scope": "DATA",
  "signature": "JYMhtSOJdqxXJHi0C0EqhfRu7mFnsUmqxICVNgRZrOgj391Z0K98SzqvWKCx7GC63ms/8nzC3BklUqBpcbQGPY7UJt5x+qLFidow7s1/THb/gZw/Ukpg4zDxqa9YikmJu9HTkWPVJC8y7PwoxRkgWqTnsCgyfkJf6kuiusUMq0TGBxNEZcxkkLDvM2UFLL/PqKFQy+WqEz712QDwtY80H9s92jAbCa/frFF7hR60rCy7lLBtzLOTB14tNLeHCj5e+2931Gy6bvHlXPNowJdL7lmWXrDLYdwjMoQH7GrlizTgJXTQzK4xm6RiRrDdJnOlXICQxqE1iVC59yFLy700Ig==",
  "by": "DATA",
  "hash": "c4575a343793dde67655cfaf3b1be4dcbbf5e8a6f59d33e525a0b5004becde12",
  "": "}\n\n",
  "__cache": {}
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="curl" %}
{% code overflow="wrap" %}

```bash
curl --location --request GET 'https://test-001-node.cloud.nxtfi.org/v2/_height/data/2'
```

{% endcode %}
{% endtab %}
{% endtabs %}


# Get files from storage by scope

Syntax for getting directories and files content from storage

## Obtain file content from storage by scope

<mark style="color:blue;">`GET`</mark> `https://test-001-node.cloud.nxtfi.org/v2 /_storage/<scope>/<dirName>/<fileName>`

If the file was saved without being placed inside a folder-like filename, the `<dirname>` part can be left out.&#x20;

If the query call point to a directory, the response will display only files listed in the specified key (directory).&#x20;

if listing folders as well as files is needed, the query call to the directory must include the query string with the raw option set to true (`/_storage/<scope>/<dirName>/?raw=1`)

#### Query Parameters

| Name                                       | Type   | Description                             |
| ------------------------------------------ | ------ | --------------------------------------- |
| scope<mark style="color:red;">\*</mark>    | String | scope were file or directory was stored |
| filename<mark style="color:red;">\*</mark> | String | Path to file                            |
| dirname                                    | String | folder like prefix name                 |

{% tabs %}
{% tab title="200: OK " %}

{% endtab %}
{% endtabs %}

### Another available option&#x20;


# Storage tracking interactions

A utility designed for transparency in tracking interactions with the storage system.

Every interaction of a block with the NxtFi storage is tracked within a file system. Whenever data is stored, modified, or deleted from the storage, a file is created with the timestamp of the transaction as its name. The content of this file is the actual hash of the block that executed the interaction. This ensures a complete and secure trace of the lifecycle of every piece of data.

## Obtain a list of the time stamps on which this file was stored/ modified

<mark style="color:blue;">`GET`</mark> `https://test-001-node.cloud.nxtfi.org/v2 /_trace/<scope>/<dirname>/<filename>/`

#### Query Parameters

| Name                                       | Type   | Description                |
| ------------------------------------------ | ------ | -------------------------- |
| scope<mark style="color:red;">\*</mark>    | String | scope were to query track  |
| filename<mark style="color:red;">\*</mark> | String | Path to file trace folder. |
| dirname                                    | String | folder-like prefix name    |

{% hint style="info" %}
Remember this calls should end with `'/'` as they point towards a list of interactions over the file.
{% endhint %}


# Storage tracking timestamp block info

A utility designed for transparency in tracking interactions with the storage system.

Retrieve detailed tracking information about the block that stores, modifies, or deletes a file in the storage.

## Get the hash value of the block that has interacted with the storage system.

<mark style="color:blue;">`GET`</mark> `https://test-001-node.cloud.nxtfi.org/v2 /<scope>/_trace/<dirname>/<filename>/<timestamp>`

#### Query Parameters

| Name                                        | Type   | Description                                                  |
| ------------------------------------------- | ------ | ------------------------------------------------------------ |
| scope<mark style="color:red;">\*</mark>     | String | scope were to query track                                    |
| dirname                                     | String | optional in case the file was stored nested into a directory |
| filename<mark style="color:red;">\*</mark>  | String | filename from which to receive track information             |
| timestamp<mark style="color:red;">\*</mark> | String | timestamp from the traced interaction                        |

### Another available endpoint&#x20;

<mark style="color:blue;">`GET`</mark> `https://test-001-node.cloud.nxtfi.org/v2/_trace/<scope>/<dirname>/<filename>/<timestamp>`


# Submit new block

Put a new block into the blockchain

## Creates a new block

<mark style="color:orange;">`PUT`</mark> `https://test-001-node.cloud.nxtfi.tech/v2/newBlock`

#### Request Body

| Name                                        | Type   | Description                                                                                                                                           |
| ------------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| prevhash<mark style="color:red;">\*</mark>  | String | Last recorded hash of the scope                                                                                                                       |
| height<mark style="color:red;">\*</mark>    | Number | Heght of the last block of the scope + 1                                                                                                              |
| version<mark style="color:red;">\*</mark>   | Number | API version                                                                                                                                           |
| data<mark style="color:red;">\*</mark>      | String | Block Content                                                                                                                                         |
| timestamp<mark style="color:red;">\*</mark> | Number | Timestamp in [Unix](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#the_ecmascript_epoch_and_timestamps) format |
| by<mark style="color:red;">\*</mark>        | String | Transaction Signer name                                                                                                                               |
| scope<mark style="color:red;">\*</mark>     | String | Scope name                                                                                                                                            |
| signature<mark style="color:red;">\*</mark> | String | <p>RSA-PSS signature of the object</p><p><code>{ prevHash, height, version, data, timestamp, scope }</code></p>                                       |
| hash<mark style="color:red;">\*</mark>      | String | Cryptographic hash (digest) encrypted with [SHA-256](https://en.wikipedia.org/wiki/SHA-2)                                                             |

{% tabs %}
{% tab title="200: OK Block successfully created" %}

{% endtab %}
{% endtabs %}

### Example in curl

{% tabs %}
{% tab title="Curl" %}

```bash
curl --location --request PUT 'https://test-001-node.cloud.nxtfi.tech/v2/newBlock' \
--header 'Content-Type: application/json' \
--data-raw '{
    "prevHash": "bd125e337f0cc7782b0e3465157b60535151362220f490650bed6b4be69bbb4b",
    "height": 14,
    "version": 2,
    "data": "Hello World!",
    "timestamp": 1676462543625,
    "scope": "DATA",
    "signature": "Vicd0mJ1mtXHleomOYsZ1oIZCeu+5P6EZLP/yRAABbvueTdMmJ1YbfnrbQ44ZJtAVwTI0NljyDoU62QvgnTEyCaJWwGR9URW+cAf15tupbkefJWrawmTOWuu3p4kBbOlF2Vk2oClnsUOpUrnzQ7AfdTa30bH87xpHLPUlvmxMw3Q3iCBH8908chKO/t/b7bI/8PGVDejYx13g2UCvJB0dcFHS8XAhAE0NwKpN33KVLCGAc5EoxLKF2mTCw5EejGxh19DbK05RbRZ8GL2j5MikyFlYVZexRIs6T3Rwr5zBacm1xw+P52WHRaDDHyAkVKd3XCvN6P18HRJWd5he+IOiw==",
    "by": "DATA",
    "hash": "d1966d2adabdcd65eb904dec2abc1179f02e2e6a5b3428e4ddf05d3a9a7a0276"
}'
```

{% endtab %}
{% endtabs %}

### Response

```javascript
{
    "verified": true,
    "queued": true
}
```


# Presign media file upload

Requesting PreSign Url for uploading media file

## Send JWT signature and public key for authentication process.

<mark style="color:orange;">`PUT`</mark> `https://test-001-node.cloud.nxtfi.org/v2/newfile`

#### Headers

| Name                                           | Type   | Description      |
| ---------------------------------------------- | ------ | ---------------- |
| Content-Type<mark style="color:red;">\*</mark> | String | application/json |

#### Request Body

| Name                                   | Type   | Description   |
| -------------------------------------- | ------ | ------------- |
| jwt <mark style="color:red;">\*</mark> | String | jwt signature |

{% tabs %}
{% tab title="200: OK obj response including Url, Field keys, and JWT payload" %}
If the Jwt is successfully verified as being signed by the private key holder, a 200 response is received.

Example response.body :

```javascript
{
    "url": "https://s3.amazonaws.com/nxtfi-bucket-us-east-1",
    "fields": {
        "key": "blockchain/v2/test-001/_archivetemp/__<scope>/37857bfd052ca152695cb5c0ef870521933b98d4a6dc0a1f8de24b6a28e55b27",
        "bucket": "nxtfi-bucket-us-east-1",
        "X-Amz-Algorithm": "AWS4-HMAC-SHA256",
        "X-Amz-Credential": "ASIA4L4KT2AK3CPJDTUF/20230609/us-east-1/s3/aws4_request",
        "X-Amz-Date": "20230609T204216Z",
        "X-Amz-Security-Token": "IQoJb3JpZ2luX2VjEE0aCXVzLWVhc3QtMSJHMEUCIQCtADIKD2gusrLoMCf1qYiao73RKcH+AgBjuhwQj+MW1wIgY+T8hL+vYUgyzWrdPW05WJaZWaaCziullcSP2yxbQqkqngMIlv//////////ARAAGgw4NTAxNTczNTkxMjUiDOZBdrwU7/g715U0jiryAnFaRvuLUiiSpu734eZF6i8ya3YMqBUwI2GpFyakpqj3Cg4VrAS6SJ3Y7tcBUigwjFQuM0ZK0YOuLFaRyB13n1YQHP+RPCIYWTmYiCZ3eRHVofQ/iX0uNPAoZileTwRzKzDf2SfVP0DVOr1FVU9N5cd4Aw+rYK64eknGBPXfpaW9TgFxAzmLBJWViQblV669vwyeQmFaRRKWJJVRGrzKDU7UjTvbRJBhGMkEBm7i+eHVEYjEdYWfpndOTg/r+6EVPQnknmRRrK2iRNY58i7eRi9ccmTIUYGDxiTLHsGqlJvzn6KPz8qizcAuc3CukoIJ1Xd0o2Ku/OIaCgimrokzK5W95y2IjzeN91UD2AsbYKu8rYqsjyg0puAMpUwnlu7hU+F5ugJQDUUIdakscjZRNhIprFqa7B8pIm8xRDWnJ2SrOApyCRBDfWmhYfo53QkNn1SjgYS3Lqg0aMPj3NtXo8+rCFeGQcPmRFqqXQEs8KKLlqEwzJuOpAY6nQFgjeeZ6Npl3F9d6/HIW4i7uU0lORWRN8dRcLhrZhEC+x6FmRP4VWjfWnFpiWYmTQGpF6roXQVI8mqIjHZgZKPKB29imjca2+rW8KX/HGmwfKT/M6UIsPkRQJ/Sz9UaQlqKMQzopMpc7Y4K/UtYtKFC94ueCtjf7IDmNboksKNwzN/rUVF9eikKjT/oRaaRLzagb8cvsmTaQsWHwWyR",
        "Policy": "eyJleHBpcmF0aW9uIjoiMjAyMy0wNi0wOVQyMTo0MjoxNloiLCJjb25kaXRpb25zIjpbWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MF0seyJhY2wiOiJwdWJsaWMtcmVhZCJ9LHsia2V5IjoiYmxvY2tjaGFpbi92Mi90ZXN0LTAwMS9fYXJjaGl2ZXRlbXAvX19iMmZpX19vbmJvYXJkaW5nLzM3ODU3YmZhMDUyY2ExNTI2OTVjYjVjMGVmODcwNTIxOTMzYjk4ZDRhNmRjMGExZjhkZTI0YjZhMjhlNTViMjcifSx7ImJ1Y2tldCI6Im54dGZpLWJ1Y2tldC11cy1lYXN0LTEifSx7IlgtQW16LUFsZ29yaXRobSI6IkFXUzQtSE1BQy1TSEEyNTYifSx7IlgtQW16LUNyZWRlbnRpYWwiOiJBU0lBNEw0S1QyQUszQ1BKRFRVRi8yMDIzMDYwOS91cy1lYXN0LTEvczMvYXdzNF9yZXF1ZXN0In0seyJYLUFtei1EYXRlIjoiMjAyMzA2MDlUMjA0MjE2WiJ9LHsiWC1BbXotU2VjdXJpdHktVG9rZW4iOiJJUW9KYjNKcFoybHVYMlZqRUUwYUNYVnpMV1ZoYzNRdE1TSkhNRVVDSVFDdEFESUtEMmd1c3JMb01DZjFxWWlhbzczUktjSCtBZ0JqdWh3UWorTVcxd0lnWStUOGhMK3ZZVWd5eldyZFBXMDVXSmFaV2FhQ3ppdWxsY1NQMnl4YlFxa3FuZ01JbHYvLy8vLy8vLy8vQVJBQUdndzROVEF4TlRjek5Ua3hNalVpRE9aQmRyd1U3L2c3MTVVMGppcnlBbkZhUnZ1TFVpaVNwdTczNGVaRjZpOHlhM1lNcUJVd0kyR3BGeWFrcHFqM0NnNFZyQVM2U0ozWTd0Y0JVaWd3akZRdU0wWkswWU91TEZhUnlCMTNuMVlRSFArUlBDSVlXVG1ZaUNaM2VSSFZvZlEvaVgwdU5QQW9aaWxlVHdSekt6RGYyU2ZWUDBEVk9yMUZWVTlONWNkNEF3K3JZSzY0ZWtuR0JQWGZwYVc5VGdGeEF6bUxCSldWaVFibFY2Njl2d3llUW1GYVJSS1dKSlZSR3J6S0RVN1VqVHZiUkpCaEdNa0VCbTdpK2VIVkVZakVkWVdmcG5kT1RnL3IrNkVWUFFua25tUlJySzJpUk5ZNThpN2VSaTljY21USVVZR0R4aVRMSHNHcWxKdnpuNktQejhxaXpjQXVjM0N1a29JSjFYZDBvMkt1L09JYUNnaW1yb2t6SzVXOTV5MklqemVOOTFVRDJBc2JZS3U4cllxc2p5ZzBwdUFNcFV3bmx1N2hVK0Y1dWdKUURVVUlkYWtzY2paUk5oSXByRnFhN0I4cEltOHhSRFduSjJTck9BcHlDUkJEZldtaFlmbzUzUWtObjFTamdZUzNMcWcwYU1QajNOdFhvOCtyQ0ZlR1FjUG1SRnFxWFFFczhLS0xscUV3ekp1T3BBWTZuUUZnamVlWjZOcGwzRjlkNi9ISVc0aTd1VTBsT1JXUk44ZFJjTGhyWmhFQyt4NkZtUlA0VldqZlduRnBpV1ltVFFHcEY2cm9YUVZJOG1xSWpIWmdaS1BLQjI5aW1qY2EyK3JXOEtYL0hHbXdmS1QvTTZVSXNQa1JRSi9TejlVYVFscUtNUXpvcE1wYzdZNEsvVXRZdEtGQzk0dWVDdGpmN0lEbU5ib2tzS053ek4vclVWRjllaWtLalQvb1JhYVJMemFnYjhjdnNtVGFRc1dId1d5UiJ9XX0=",
        "X-Amz-Signature": "c81fc89db78e4f2287efbfa9d1139ec8fd4c268cc15323d14b21f97497e0a0e1"
    },
    "payload": {
        "by": "entity",
        "fileHash": "de4c62edfd77fbe4c6e2b2f5f34a26e39857530fe4147abfc0c245318e89465e",
        "fileSize": 631025,
        "iat": 1689693962,
        "exp": 1689780362
    }
}
```

{% endtab %}
{% endtabs %}

If the Jwt is successfully verified as being signed by the private key holder, a 200 response is received.

Example response.body :

```javascript
{
    "url": "https://s3.amazonaws.com/nxtfi-bucket-us-east-1",
    "fields": {
        "key": "blockchain/v2/test-001/_archivetemp/__b2fi__onboarding/37857bfa052ca152695cb5c0ef870521933b98d4a6dc0a1f8de24b6a28e55b27",
        "bucket": "nxtfi-bucket-us-east-1",
        "X-Amz-Algorithm": "AWS4-HMAC-SHA256",
        "X-Amz-Credential": "ASIA4L4KT2AK3CPJDTUF/20230609/us-east-1/s3/aws4_request",
        "X-Amz-Date": "20230609T204216Z",
        "X-Amz-Security-Token": "IQoJb3JpZ2luX2VjEE0aCXVzLWVhc3QtMSJHMEUCIQCtADIKD2gusrLoMCf1qYiao73RKcH+AgBjuhwQj+MW1wIgY+T8hL+vYUgyzWrdPW05WJaZWaaCziullcSP2yxbQqkqngMIlv//////////ARAAGgw4NTAxNTczNTkxMjUiDOZBdrwU7/g715U0jiryAnFaRvuLUiiSpu734eZF6i8ya3YMqBUwI2GpFyakpqj3Cg4VrAS6SJ3Y7tcBUigwjFQuM0ZK0YOuLFaRyB13n1YQHP+RPCIYWTmYiCZ3eRHVofQ/iX0uNPAoZileTwRzKzDf2SfVP0DVOr1FVU9N5cd4Aw+rYK64eknGBPXfpaW9TgFxAzmLBJWViQblV669vwyeQmFaRRKWJJVRGrzKDU7UjTvbRJBhGMkEBm7i+eHVEYjEdYWfpndOTg/r+6EVPQnknmRRrK2iRNY58i7eRi9ccmTIUYGDxiTLHsGqlJvzn6KPz8qizcAuc3CukoIJ1Xd0o2Ku/OIaCgimrokzK5W95y2IjzeN91UD2AsbYKu8rYqsjyg0puAMpUwnlu7hU+F5ugJQDUUIdakscjZRNhIprFqa7B8pIm8xRDWnJ2SrOApyCRBDfWmhYfo53QkNn1SjgYS3Lqg0aMPj3NtXo8+rCFeGQcPmRFqqXQEs8KKLlqEwzJuOpAY6nQFgjeeZ6Npl3F9d6/HIW4i7uU0lORWRN8dRcLhrZhEC+x6FmRP4VWjfWnFpiWYmTQGpF6roXQVI8mqIjHZgZKPKB29imjca2+rW8KX/HGmwfKT/M6UIsPkRQJ/Sz9UaQlqKMQzopMpc7Y4K/UtYtKFC94ueCtjf7IDmNboksKNwzN/rUVF9eikKjT/oRaaRLzagb8cvsmTaQsWHwWyR",
        "Policy": "eyJleHBpcmF0aW9uIjoiMjAyMy0wNi0wOVQyMTo0MjoxNloiLCJjb25kaXRpb25zIjpbWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MF0seyJhY2wiOiJwdWJsaWMtcmVhZCJ9LHsia2V5IjoiYmxvY2tjaGFpbi92Mi90ZXN0LTAwMS9fYXJjaGl2ZXRlbXAvX19iMmZpX19vbmJvYXJkaW5nLzM3ODU3YmZhMDUyY2ExNTI2OTVjYjVjMGVmODcwNTIxOTMzYjk4ZDRhNmRjMGExZjhkZTI0YjZhMjhlNTViMjcifSx7ImJ1Y2tldCI6Im54dGZpLWJ1Y2tldC11cy1lYXN0LTEifSx7IlgtQW16LUFsZ29yaXRobSI6IkFXUzQtSE1BQy1TSEEyNTYifSx7IlgtQW16LUNyZWRlbnRpYWwiOiJBU0lBNEw0S1QyQUszQ1BKRFRVRi8yMDIzMDYwOS91cy1lYXN0LTEvczMvYXdzNF9yZXF1ZXN0In0seyJYLUFtei1EYXRlIjoiMjAyMzA2MDlUMjA0MjE2WiJ9LHsiWC1BbXotU2VjdXJpdHktVG9rZW4iOiJJUW9KYjNKcFoybHVYMlZqRUUwYUNYVnpMV1ZoYzNRdE1TSkhNRVVDSVFDdEFESUtEMmd1c3JMb01DZjFxWWlhbzczUktjSCtBZ0JqdWh3UWorTVcxd0lnWStUOGhMK3ZZVWd5eldyZFBXMDVXSmFaV2FhQ3ppdWxsY1NQMnl4YlFxa3FuZ01JbHYvLy8vLy8vLy8vQVJBQUdndzROVEF4TlRjek5Ua3hNalVpRE9aQmRyd1U3L2c3MTVVMGppcnlBbkZhUnZ1TFVpaVNwdTczNGVaRjZpOHlhM1lNcUJVd0kyR3BGeWFrcHFqM0NnNFZyQVM2U0ozWTd0Y0JVaWd3akZRdU0wWkswWU91TEZhUnlCMTNuMVlRSFArUlBDSVlXVG1ZaUNaM2VSSFZvZlEvaVgwdU5QQW9aaWxlVHdSekt6RGYyU2ZWUDBEVk9yMUZWVTlONWNkNEF3K3JZSzY0ZWtuR0JQWGZwYVc5VGdGeEF6bUxCSldWaVFibFY2Njl2d3llUW1GYVJSS1dKSlZSR3J6S0RVN1VqVHZiUkpCaEdNa0VCbTdpK2VIVkVZakVkWVdmcG5kT1RnL3IrNkVWUFFua25tUlJySzJpUk5ZNThpN2VSaTljY21USVVZR0R4aVRMSHNHcWxKdnpuNktQejhxaXpjQXVjM0N1a29JSjFYZDBvMkt1L09JYUNnaW1yb2t6SzVXOTV5MklqemVOOTFVRDJBc2JZS3U4cllxc2p5ZzBwdUFNcFV3bmx1N2hVK0Y1dWdKUURVVUlkYWtzY2paUk5oSXByRnFhN0I4cEltOHhSRFduSjJTck9BcHlDUkJEZldtaFlmbzUzUWtObjFTamdZUzNMcWcwYU1QajNOdFhvOCtyQ0ZlR1FjUG1SRnFxWFFFczhLS0xscUV3ekp1T3BBWTZuUUZnamVlWjZOcGwzRjlkNi9ISVc0aTd1VTBsT1JXUk44ZFJjTGhyWmhFQyt4NkZtUlA0VldqZlduRnBpV1ltVFFHcEY2cm9YUVZJOG1xSWpIWmdaS1BLQjI5aW1qY2EyK3JXOEtYL0hHbXdmS1QvTTZVSXNQa1JRSi9TejlVYVFscUtNUXpvcE1wYzdZNEsvVXRZdEtGQzk0dWVDdGpmN0lEbU5ib2tzS053ek4vclVWRjllaWtLalQvb1JhYVJMemFnYjhjdnNtVGFRc1dId1d5UiJ9XX0=",
        "X-Amz-Signature": "c81fc89db78e4f2287efbfa9d1139ec8fd4c268cc15323d14b21f97497e0a0e1"
    },
    "payload": {
        "by": "entity",
        "fileHash": "de4c62ed3d77fbe2c6e2b2f5f34a26e39857530fe4147abfc0c245318e89465e",
        "fileSize": 631025,
        "iat": 1689693962,
        "exp": 1689780362
    }
}
```


