# What is AI Network

AI Network is a global backend infrastructure that transforms millions of open source projects into live services (a.k.a. Open Resource). This document outlines event-driven blockchain platform that aims to initiate innovation in the decentralized application economy, particularly for AI programs. To further understand our vision, refer to the following whitepaper.

{% file src="/files/50HYRg7xuANqklHHV8jx" %}


# Architecture

Blockchain for Serverless Computing

#### **Background**

AI Network was highly motivated by the idea behind Ethereum’s Turing completeness and world computer. A network in which every node verifies code execution can provide unprecedented security and immutability in the permissionless network. However, despite the considerable improvement over a few years, the performance of the smart contract still remains inadequate in terms of being capable of handling operations for all projected global applications. By design, scalability of Ethereum is limited by its own strength which can be summarized as statefulness, trustlessness, and serialized operation.

When designing modern serverless architecture, applications achieve high scalability through statelessness, permission, and concurrent operations. By decoupling computation from blockchain, AI Network can perform large scale operations in a serverless architecture. At the same time, AI Network blockchain is designed as a lightweight ledger that can process millions of transactions per second and safely record communication between clients and workers. The detailed differences between AI Network, blockchains, and serverless architectures are described in the following diagram.<br>

|               | **Blockchain** | **Serverless** | **AI Network**                                                                                        |
| ------------- | -------------- | -------------- | ----------------------------------------------------------------------------------------------------- |
| Operation     | Stateful       | Stateless      | <p>Balance/Rules/Trigger State: Stateful</p><p>Value State: Stateless</p>                             |
| Access        | Permissionless | Permissioned   | <p>Blockchain Validator: Permissionless</p><p>Trigger: Permissioned/Permissionless (configurable)</p> |
| Storage       | Persistent     | Ephemeral      | Persistent                                                                                            |
| Network       | Distributed    | Decentralized  | Distributed                                                                                           |
| Scalability   | Low            | High           | High                                                                                                  |
| Latency       | High           | Low            | Low                                                                                                   |
| Data Capacity | Low            | High           | High                                                                                                  |
| Concurrency   | Serialized     | Concurrent     | Concurrent                                                                                            |
| Language      | Monoglot       | Polyglot       | Polyglot                                                                                              |

Table 1. Comparison between blockchain, serverless, and AI Network. AI Network uses blockchain as a lightweight communication channel and adapts serverless architecture for computation.<br>

#### **Blockchain for Serverless Computing**<br>

Function as a service (FaaS) is a platform allowing customers to develop, run, and manage application functionalities without the complexity of building and maintaining the infrastructure. Although FaaS is often used as a category of cloud service, it is interesting to notice that Ethereum can also provide similar characteristics. Especially, Web IDEs for solidity such as remix ([https://remix.ethereum.org](https://remix.ethereum.org/)) enable developers to develop Solidity contracts straight from the browser, and then deploy to Ethereum network. Once it is deployed, EVM in Ethereum nodes run the functions, and developers don’t have to worry about maintaining the infrastructure. Furthermore, unlike cloud functions that can be stopped and modified as developers require, deployed functions are managed forever, unless the function has exposed the self-destruction method.

Despite the similarities, Ethereum is far from a general purpose FaaS because (1) It only supports Solidity. (2) Operations are expensive. (3) It can only interact with Ethereum’s internal state, and cannot call other components such as external databases and APIs.&#x20;

![](/files/-LsRK5uAa0Z7r5xRfx-T)

Fig 1. EVM runs contracts and contracts need not to be managed by developers once they are deployed. In this respect, Ethereum can be viewed as a very slow and expensive Function as a Service. Unlike monoglot Ethereum, AI Network runs a variety of languages on heterogeneous types of runtime environments. We refer to these environments as Secure Runtime Environment, or SRE for short.

AI Network deploys functions to the blockchain just like Ethereum, but it can also (1) support all available languages and framework, (2) cost less than major cloud services, and (3) can interact with off-chain components if necessary.<br>

| <p></p><p></p><p><img src="/files/-LsRKZBer0D0I_UJdXXy" alt=""></p><p></p> | <p></p><p><img src="/files/-LsRKa9KgpiGLsbS2pTU" alt=""></p> |
| -------------------------------------------------------------------------- | ------------------------------------------------------------ |

Fig 2. Ethereum supports only one language (Solidity) and one virtual machine (EVM), and all nodes execute the same transactions. AI Network can support multiple languages and several types of SREs host different types of functions. While blockchain records transactions, execution for the transaction happens on off-chain worker nodes.

For more information, refer to the [AI Network Architecture Paper](https://www.ainetwork.ai/public/architecture.pdf)


# Design Principles

AI Network blockchain is responsible for managing uploaded programs, resource providers, and incoming requests from clients. AIN blockchain design principles are as follows:

1. Asynchronous & Stateless: All Ethereum smart contract operations are stateful, and contract calls cannot be executed in parallel. AIN blockchain starts operation by setting a value for the path in the blockchain's database. Each worker for this operation then records their result in this designated path. Unless there are duplicated attempts to change the value of the path at the same time, operations can run in parallel.&#x20;
2. Composable: Developers often use third-party API to enhance the application’s features, but maintaining upgrades from different API providers is not an easy task. In the worst case, API providers may switch their billing plans or deprecate old APIs which may be critical to operating applications. AI Network functions can become ownerless like blockchain smart contracts, and developers no longer have to worry about functions being modified unexpectedly. This enables developers to design stable microservice architecture for their applications.
3. Lightweight & Fast: Transactions store a very small amount of data (\~250bytes), which is transmitted to the network through a gossip protocol. While blockchain nodes are capable of quickly recording these lightweight transactions at scale, workers are also free to join anytime and can start processing jobs triggered by the blockchain state change.
4. Sharding: AIN blockchain stores database state in a tree structure. This allows the database to be easily partitioned into multiple sub-trees. Besides genesis PoS rules, each partitioned sub-tree may define its own consensus rules and maintain small blockchain for each sub-tree.<br>


# Event-driven Architectures

\
AI Network works as event-driven application backend. The lifecycle of application request is as follows.

1. Client (dApp) sends transactions to blockchain
2. Block state of blockchain node is updated by the transaction.
3. Block state listener listens to the path and triggers event to the worker.
4. AIN workers executes functions for the path and may generate another transactions. If it generates another transaction it goes to (2) and updates block state.
5. Dapp registers listener to the blockchain data and gets result through the modified blockchain state.

In traditional server-based computing, users need to prepare the server, install OS and necessary drivers and software. Then, users need to manage servers and take care of hardware and software upgrades. To maintain highly-available and scalable servers, users also need to configure load-balancers. The idea behind serverless computing is for developers to focus on writing application code.

![](/files/-LsP9Hvd8kw7OEH41q0r)

Figure1. AIN Triggers listen for value changes of specific paths in the blockchain state. When a trigger is invoked, AIN workers generate additional transactions as a result. These additional transactions may subsequently trigger other workers if necessary.<br>


# Blockchain Database

Ethereum is a global singleton state machine, transactions trigger a change of state or cause a contract to execute in the EVM. The contract execution part is the heavy part which requires both virtual machine and storage structure. The smart contract transaction can be divided into three functionalities: changing state, defining rules for changing state, and defining actions when changing state. While Ethereum handles all three functionalities through blockchain transactions, AIN network aims to provide this functionality through states, rules, and triggers.

Transactions in AI Network trigger a change of state or defines the rules for changing state. The difference is it does not contain the code and the node does not need extra storage or memory for running the code on-chain. Rules are a small amount of the expression to dictate which transactions are valid and accepted for the specified subset of the state. In this regard, rules provide integrity to data written to the blockchain, ensuring invalid transactions are not allowed. Finally, triggers are off-chain workers which may generate additional transactions in response to transactions that have already been processed by the blockchain.

AI Network's state manipulation module is often refer to as *blockchain database* as it's very similar to traditional NOSQL database in the ways they read and write data.


# States

AIN blockchain has tree-structured state models shared to all peers in the network. State consists of a collection of key-value pairs.

The state of the blockchain-database is determined by both the total set of transactions which have been added to blocks in the blockchain and all valid transactions in the transactions-pool which have not yet been added to blocks. This state determines what subsequent transactions are allowed, as well as containing information on all previous transactions and blocks that have occurred up to the current state.

![](/files/-LsP9WT0GAoQ_5nyrNKZ)

Figure 1: Each new transaction builds upon the blockchain-database state that was left by the previous transaction. Each new transaction request is automatically assigned an ID and a nonce which is a +1 increment from the previous transaction. Additional transaction fields (gas, parentTxID. etc,) were omitted for space. <br>


# State Types

Basically there are three types of blockchain states: values, rules, and owners.

| Type      | Content                                                                            |
| --------- | ---------------------------------------------------------------------------------- |
| values    | Database values e.g. account balance                                               |
| rules     | Database rules to determine who has value write permissions                        |
| owners    | Database owners to determine who has ownership to change rules or ownership itself |
| functions | Database functions triggered by value change                                       |

All access APIs and internal data structure for each state type are designed to be separate. For example, they use different root nodes in the internal key-value pair tree structure.


# Operations

Blockchain state can be accessed using state access operations. There are two types of operations, *read operation* and *write operation*, and they are again classified into two categories: *simple operation* and *composite operation*. Simple operations are those that have only one access reference point (i.e., data path in the blockchain database), while composite operations have multiple access reference points.

## Read Operations

There is no permission required for read operations.

### Simple Operations

| Target   | Operator      | Parameters                     | Action                                               |
| -------- | ------------- | ------------------------------ | ---------------------------------------------------- |
| value    | GET\_VALUE    | ref                            | Get the value on the path reference                  |
| rule     | GET\_RULE     | ref                            | Get the rule config on the path reference            |
| owner    | GET\_OWNER    | ref                            | Get the owner config on the path reference           |
| function | GET\_FUNCTION | ref                            | Get a triggering function hash on the path reference |
| rule     | EVAL\_RULE    | ref, address, value, timestamp | Evaluate the rule config on the path reference       |
| owner    | EVAL\_OWNER   | ref, address                   | Evaluate the owner config on the path reference      |

### Composite Operations

| Target                          | Operator | Parameters                        | Action                                                                 | Rule requirements |
| ------------------------------- | -------- | --------------------------------- | ---------------------------------------------------------------------- | ----------------- |
| value, rule, owner, or function | GET      | op\_list (list of get operations) | Get multiple path-value, path-rule, path-owner, or path-function pairs | None              |

## Write Operations

Each write operation has permission requirements depending on its type and path reference.

### Simple Operations

| Target   | Operator      | Parameters    | Action                                             | Required Permission                   |
| -------- | ------------- | ------------- | -------------------------------------------------- | ------------------------------------- |
| value    | SET\_VALUE    | ref, value    | Set the value on the path reference                | Value write permission on the path    |
| value    | INC\_VALUE    | ref, value    | Increment the value on the path reference by delta | Value write permission on the path    |
| value    | DEC\_VALUE    | ref, value    | Decrement the value on the path reference by delta | Value write permission on the path    |
| rule     | SET\_RULE     | ref, rule     | Set the rule on the path reference                 | Rule write permission on the path     |
| owner    | SET\_OWNER    | ref, owner    | Set the owner on the path reference                | Owner write permission on the path    |
| function | SET\_FUNCTION | ref, funcHash | Set a triggering function on the path reference    | Function write permission on the path |

### Composite Operations

There are two composite write operations, SET and BATCH:

| Target                          | Operator | Parameters                          | Action                                                                 | Rule requirements                                 |
| ------------------------------- | -------- | ----------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------- |
| value, rule, owner, or function | SET      | op\_list (an array of operations)   | Set multiple path-value, path-rule, path-owner, or path-function pairs | Write permission on **all** the paths             |
| value, rule, owner, or function | BATCH    | tx\_list (an array of transactions) | Handle each transaction independently                                  | Write permission on the paths of each transaction |

The SET and BATCH operations can be compared as follows:

| Comparison | SET Operation                                                       | BATCH Operation                                                                                                              |
| ---------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| structure  | Has multiple operations in op\_list                                 | Has multiple transactions in tx\_list                                                                                        |
| atomicity  | The whole operation fails if one of the operation in op\_list fails | The transactions in tx\_list are executed independently, i.e., failure of one transaction does not affect other transactions |
| order      | Broadcasted in a bundle and executed in the given order             | Broadcasted in a bundle and executed in the given order                                                                      |


# Predefined Structures

## Reserved Characters in Paths

In data paths, the following characters are reserved:

| Characters                                        | Purpose                                           | Example                                                                                                                                         |
| ------------------------------------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| /                                                 | Reserved for path separator                       | /apps/afan/users                                                                                                                                |
| .                                                 | Reserved for rule configs and owner configs       | <p>{</p><p>  .write: false,</p><p>  ...</p>                                                                                                     |
| \*                                                | Reserved for owner configs                        | <p>{ </p><p>  "apps": {<br>    ".owner": {<br>      "owners": {</p><p>        "\*": {</p><p>...</p>                                             |
| $                                                 | Reserved for path variables in rule configs       | <p>{</p><p>  transfer: {</p><p>    $from: {</p><p>      $to: {</p><p>        $key: {</p><p>          value: {</p><p>            .write: ...</p> |
| {, }                                              | Reserved for variables in built-in function paths | /transfer/{from}/{to}/{key}/value                                                                                                               |
| #, \[, ], \<ASCII control characters 0-31 or 127> | Reserved for other purposes in the future         | -                                                                                                                                               |

## Pre-defined Paths in Database

The following pre-defined paths are used in the blockchain database:

| Path                                                  | Purpose            |
| ----------------------------------------------------- | ------------------ |
| /accounts/$address/balance                            | Account balance    |
| /accounts/$address/nonce                              | Account nonce      |
| /apps                                                 | Applications       |
| /consensus                                            | Consensus          |
| /checkin                                              | Check-in           |
| /deposit/$service\_id/$address/$deposit\_id           | Deposit            |
| /deposit\_accounts/$service\_id/$address/$account\_id | Deposit accounts   |
| /escrow                                               | Escrow             |
| /payments                                             | Payment            |
| /sharding                                             | Sharding           |
| /token/name                                           | Token name         |
| /token/symbol                                         | Token symbol       |
| /token/total\_supply                                  | Token total supply |
| /transfer/$from/$to/$key/value                        | Transfer           |
| /withdraw/$service\_id/$address/$withdraw\_id         | Withdraw           |

Owner configs and rule configs are stored in separate places in the database.


# Rules and Owners

Rule configs are used to determine the validity of transactions before they are executed. Rule configs are also used to control which users are able to make certain types of transactions. Rule values are javascript boolean statements which will be invoked whenever a user tries to write data to the blockchain-database via a transaction. These statements will evaluate to either true or false depending on - the user, the current state of the blockchain database, and the current time - to name just a couple of examples. Common rule config use cases are:

* Enforcing the terms of an agreed contract between peers on the AI Network
* Ensuring automatic payment to relevant peers once the terms of a contract have been fulfilled and all relevant transactions to that contract have been added to the blockchain
* Determining who has permission to build and validate a block at any given height of the blockchain
* Enforcing punishments for validator peers who attempt to compromise the integrity of the blockchain

To control write permissions on rule configs, we use owner configs. Owner configs are also used to control the write permissions on the owner configs themselves.


# Rule Configs

## Syntax

Rule configs are stored as a ".write" property on a path in the database using SET\_RULE operation.&#x20;

```
{
  <path>: {  // path can include variables like $key
    <to>: {
      <target_node>: {
        .write: <eval string to determine the write permission>
      }
    }
  }
}
```

Its value is an javascript eval string that will be evaluated true or false to determine users' permission on the path whenever a transaction with value write operations on the path is submitted.&#x20;

## Path Variables and Built-in Variables

The path can have path variables like "/transfer/$from/$to/value" to allow flexibility of rule expressions. In the same context, built-in variables are also provided by the system:

| Variable / Function                                   | Members | Semantic                                                                                                                                                                                                                                | Example                                                               | API Version |
| ----------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ----------- |
| auth                                                  | addr    | Sender (signer) address                                                                                                                                                                                                                 | auth.addr === '$uid'                                                  | 1.0         |
| auth                                                  | fid     | Caller (function) ID                                                                                                                                                                                                                    | auth.fid === '\_transfer'                                             | 1.0         |
| getValue(\<db path>)                                  |         | To get the value at the db path                                                                                                                                                                                                         | getValue('/accounts/' + $user\_addr + '/balance') >= 0                | 1.0         |
| getRule(\<db path>)                                   |         | To get the rule at the db path                                                                                                                                                                                                          | getRule('/apps/test\_app')                                            | 1.0         |
| getOwner(\<db path>)                                  |         | To get the owner at the db path                                                                                                                                                                                                         | <p>getOwner('/apps/test\_app')</p><p></p>                             | 1.0         |
| getFunction(\<db path>)                               |         | To get the function at the db path                                                                                                                                                                                                      | getFunction('/apps/test\_app')                                        | 1.0         |
| evalRule(\<db path>, \<value>, \<auth>, \<timestamp>) |         | To eval the rule config at the rule path                                                                                                                                                                                                | evalRule('/apps/test\_app/posts/1', 'hello world', auth, currentTime) | 1.0         |
| evalOwner(\<db path>, \<permission>, \<auth>)         |         | To eval the owner config at the owner path                                                                                                                                                                                              | evalOwner('/apps/test\_app/posts/1', 'write\_owner', auth)            | 1.0         |
| newData                                               |         | The new data to be set at the given path                                                                                                                                                                                                | getValue('/accounts/' + $user\_addr + '/balance') >= newData          | 1.0         |
| data                                                  |         | The existing data at the given path                                                                                                                                                                                                     | data !== null                                                         | 1.0         |
| currentTime                                           |         | Current timestamp                                                                                                                                                                                                                       | currentTime <= $time + 24 \* 60 \* 60                                 | 1.0         |
| lastBlockNumber                                       |         | Last block number                                                                                                                                                                                                                       | lastBlockNumber > 10000                                               | 1.0         |
| util                                                  |         | <p>A collection of various utilities</p><p>Check this link :<a href="https://github.com/ainblockchain/ain-blockchain/blob/master/db/rule-util.js"><https://github.com/ainblockchain/ain-blockchain/blob/master/db/rule-util.js></a></p> | util.isString(newData)                                                |             |

## Examples

Rule configs can be set as the following examples:

```
{
  transfer: {
    $from: {
      $to: {
        $key: {
          value: {
            .write: "auth.addr === $from && !getValue('transfer/' + $from + '/' + $to + '/' + $key) && getValue(util.getBalancePath($from)) >= newData"
          }
        }
      }
    }
  },
  apps: {
    afan: {
      .write: "auth.addr === '0x12345678901234567890123456789012345678'",
      follow: {
        $uid: {
          .write: "auth.addr === $uid"
        }
      }
    }
  }
}
```

There is no ‘read’ permission in data access. It means all network participants can read your data. To secure data on specific node path, users need to encrypt the data with their own private key.

## Application of Rule Configs

Permission of a value write operation (e.g. SET\_VALUE) is check as follows:

* When there are no rule configs on the requested path, closest ancestor's rule config is applied
* If there are more than one path matched, the most specific rule config is applied
  * e.g. Among a) /apps/$app\_id/$service, b) /apps/afan/$service, c) /apps/afan/wonny, c) is applied.
* When the value of the write operation in request is an object, the operation is granted when the permission check succeeds on every path of object. For example, SET\_VALUE operation is requested on /foo/bar with value { abc: "abc\_val", def: "def\_val" }, it should pass the permission check on /foo/bar, /foo/bar/abc, and /foo/bar/def.
* Rule config always overrides its ancestors' rule configs


# Owner Configs

## Syntax

Owner configs are stored as a ".owner" property on a path  in the database using SET\_OWNER operation.

```
{
  <path>: {  // path cannot include a variable like $key 
    <to>: {
      <target_node>: {
        .owner: {
          inherit: [
            "<ref1>",  // ref1 should be an ancestor node
            "<ref2>"   // ref2 should be an ancestor node
            ...
          ],
          owners: {
            "*": {
              write_owner: true | false,
              write_function: true | false,
              write_rule: true | false,
              branch_owner: true | false,
            },
            "<1st address>": {
              write_owner: true | false,
              write_rule: true | false,
              write_function: true | false,
              branch_owner: true | false,
            },
            "<2nd address>": {
              write_owner: true | false,
              write_rule: true | false,
              write_function: true | false,
              branch_owner: true | false,
            },
            ...
          }
        }
      }
    }
  }
}
```

Meaning of the syntax keywords can be summarized as follows:

| Keyword         | Semantic                                                                                                                                                                                                                                                                                                                                                   | API Version |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| write\_owner    | Property of users in owner configs. If this value is true, the user can write the owner config itself. Default value: false.                                                                                                                                                                                                                               | 1.0         |
| write\_rule     | Property of users in owner configs. If this value is true, the user can write the rule config. Default value: false.                                                                                                                                                                                                                                       | 1.0         |
| write\_function | Property of users in owner configs. If this value is true, the user can write the function config. Default value: false.                                                                                                                                                                                                                                   | 1.0         |
| branch\_owner   | Property of users in owner configs. If this value is true, the user can add a branching owner config, e.g. a user in /apps/afan/.owner can add branching owner rule /apps/afan/community/.owner. Default value: false.                                                                                                                                     | 1.0         |
| inherit         | Property of owner configs. Its value is given as an array of paths to owner configs. If it’s set, the owners on the specified paths are included in the owners. Ownership inheritance is allowed only from ancestors’ owner configs and, if there are conflicts, the descendant's owners have precedence over ancestor's owners. Default value: undefined. | TBD         |

## Examples

Owner configs can be set as the following examples:

```
{
  apps: {
    .owner: {
      owners: {
        "*": {
          write_owner: false,
          write_function: false,
          write_rule: false,
          branch_owner: true
        }
      }
    },
    afan: {
      .owner: {
        owners: {
          "0x12345678901234567890123456789012345678": {
              write_owner: true,
              write_function: true,
              write_rule: true,
              branch_owner: true
          }
        }
      }
    }
  }
}
```

## Application of Owner Configs

Write permission on a rule or owner path is check as follows:

* When there are no owner configs on the requested path, closest ancestor owner config is applied
* Owner config always overrides its ancestors' owner configs


# Functions

An application may use AIN Functions to execute the backend-code in response to blockchain events. The code is stored in an off-chain repository (a.k.a Big Storage) and can be executed in the runtime environment of workers which are operated by diverse resource providers.<br>

Unlike conventional blockchain in which smart contract operations are synchronous and serialized,  AIN Functions can be executed asynchronously in parallel. The data used in functions are passed from the blockchain state, and the results are also passed back to the blockchain state after the operation is completed. The function typically does not remember any internal state during the execution, which means each function call is independent and stateless.<br>

AI Network may provide function registry service for a client to upload function programs to the off-chain repository. Uploaded functions can be accessible by function\_hash, and the set\_function transaction may be submitted to bind the corresponding path with the function. The function starts operation by setting the function parameters in the block state of the blockchain database, and each worker writes the execution result to the designated path. The path for the parameters and result may have an associated rule to control the permission for calling function and writing the result of the function.<br>

![](/files/-LsPwllstTKLsgEy91pS)

Fig 1. The function registry service receives the function code from the client and stores it in the big storage. In return, the client receives function\_hash which can identify the location of the function when the workers try to download the function before the execution. By recording a transaction which sets function\_hash for trigger\_path of the blockchain state, the registered function can be triggered when the parameters are written to the designated trigger\_path.<br>

![](/files/-LsPwoBJAbOw0U7Ve3ea)

Fig. 2 When the blockchain receives a transaction, the block state is updated by the transaction. The blockchain event listener monitors the change of block state and transmits the event to the corresponding worker. The triggered worker executes a function and generates an additional transaction as a result of the function execution. The additional transaction generated by the worker updates the block state, and may trigger other workers for the event.

#### Quick Demo

The following shows how simple Node.js function can be deployed using AI Network function registry service and event listener. It is also possible for developers to implement custom function registry service and event listener for processing different types of functions.

1.Register function to function registry service.

functions.ainetwork.ai currently supports Node.js 8. Developers can zip their project folder which includes index.js and package.json, and it will return function\_hash which can be used for registering the function to AI Network blockchain. index.js must exports onChange for the purpose of responding to a new blockchain transaction.

{% code title="index.js" %}

```javascript
exports.onChange = (event, context) => {
  const txData = event.data;
  console.log('hello', txData)
};
```

{% endcode %}

```bash
$ curl --upload-file ./hello.zip http://functions.ainetwork.ai
{
  result: {code: 0, message: 'success'}, 
  function_hash: 0xFUNCTION_HASH
}
```

2\. Register function\_hash to blockchain database path. Developers may use custom registry\_service or event\_listener if they wish.

```javascript
ain.sendTransaction({
    operation: {type: "SET_FUNCTION", 
                ref: "path/to/value", 
                value: {registry_service: "functions.ainetwork.ai",
                        event_listener: "events.ainetwork.ai",
                        function_hash: '0xFUNCTION_HASH'}},
    nonce: 17,
    address: '0x11F26Fc7b19cB04eeAD03F3d32aeDf5A6e726dA6',
    parent_tx_hash: '0xd96c7966aa6e6155af3b0ac69ec180a905958919566e86c88aef12c94d936b5e'
})
.then(function(hash){ ... });
```

After this, hello function will be triggered whenever the value at the "path/to/value" is changed by a new transaction.


# Built-in Functions

## Built-in Functions

To apply predefined system operations, built-in functions are defined. For example, account value transfer is implemented using transfer built-in function. Each built-in function consists of triggering conditions and a function. The triggering condition is given by a database path pattern and whenever a new value is written on the path patten, the function is called. If the function fails, the transaction triggered the function call also fails.

### Transfer

```
{
  '/transfer/{from_addr}/{to_addr}/{transfer_id}/value': _transfer(value, context) {
    // Check (the balance of from_addr) >= value
    // Decrement the balance of from_addr by value
    // Increment the balance of to_addr by value
  }
}
```

### Deposit

```
{
  '/deposit/{service_id}/{addr}/{deposit_id}/value': _deposit(value, context) {
    // Check (the balance of addr) >= value
    // Decrement the balance of addr by value
    // Increment the value of /deposit_accounts/$service_id/$addr by value
    // Set /deposit_accounts/$service_id/$addr/expire_at as
    // transaction's timestamp + service's deposit lockup time, which is
    // configured at /deposit_accounts/$service_id/config/lockup_duration
  }
}
```

### Withdraw

```
{
  '/withdraw/{service_id}/{addr}/{withdraw_id}/value': _withdraw(value, context) {
    // Check the value at (/deposit_accounts/$service_id/$addr/value) >= value
    // Check (deposit_accounts/$service_id/$addr/expire_at) >= current time
    // Decrement the value of /deposit_accounts/$service_id/$addr by value
    // Increment the balance of addr by value
  }
}
```


# Instant Execution, and Eventual Consistency

Our blockchain’s  approach to transactions and rules is unique to AIN network and unlike any other commercial blockchain implementation currently in use. In their simplest form transactions merely update values in a simple key-value tree-structured database, which is being maintained by the blockchain. Rules determine whether a given user has permission to execute a transaction, given information such as the user’s publicKey, the time of transaction, and other data in the database. Through these transactions and rules, the AIN Network achieves the following characteristic features:

1. Constant liveliness & instant execution
2. Guaranteed eventual consistency
3. Predefined consensus agreements

All peer nodes - as identified through their public key - maintain both a local copy of the blockchain, and a transaction pool to store transactions (tx) that have not yet been added to the blockchain. When a peer node receives a tx, they check the tx validity and then immediately execute this tx before adding it to their local transaction pool. These tx are subsequently added to blocks which then become part of the blockchain via the AI Network’s consensus mechanism (Please refer to the consensus document for more information). Blocks in the blockchain are identical across all peer nodes. However tx in the transaction pool will not necessarily be the same across all peers (see Figure 1). The “state” of the blockchain-database is formed from the sequential execution of all tx in both the blockchain and transaction pool. In this regard, the immediate execution of tx in the transaction pool allows the AI Network to provide constant liveliness to users, while the blockchain will ensure eventual consistency of state across all peers.

User  (Public Key: Oxaaaaaaaaaa)

![](/files/-LsPxbmaUdzKjRU1mwsV)

User  (Public Key: Oxbbbbbbbbbb)<br>

![](/files/-LsPxpQG8vk6Kf-bQbF-)

Figure 1: Illustration of how transactions from both the blockchain and the transaction pool combine to create the state of the AIN blockchain database at any given time. Transactions in the blockchains are identical between the two nodes. However transactions in the transaction pool are slightly different, allowing for slight differences in state. These differences in both state and transactions in the transaction pool are highlighted in blue.  As transactions are removed from the transaction pool and added to the blockchain, consistency between states across all nodes will eventually be achieved.

This is illustrated in figure 1, where the “state” between nodes  with public keys 0xaaaaaaa and 0xbbbbbbbbbb are slightly different. This difference in state arises from differences in transactions between 0xaaaaaaa’s and 0xbbbbbbb’s ’s transaction pools. Assuming these transactions are valid, these differences between the two states will eventually be reconciled when the valid transactions in both 0xaaaaaaa’s and 0xbbbbb’s respective transaction pool get included into a block on the blockchain,&#x20;

Rules will be used to enforce predefined consensus agreements about what type of transactions will be allowed. Paths under, the rules subtree of the database determine access privileges to data at the corresponding path under the root tree for the blockchain-database “state”.<br>


# Network ID and Chain ID

The blockchain network has two identifiers, Network ID and Chain ID.

Network IDs are for blockchain node communication and Chain IDs are for signing transactions.

| Network Name           | Network ID | Chain ID |
| ---------------------- | ---------- | -------- |
| Testnet                | 0          | 0        |
| Mainnet                | 1          | 1        |
| Devnet                 | 2          | 2        |
| Reserved (to be added) | 3\~        | 3\~      |


# Transactions

Transactions are signed messages that can mutate a global singleton tree-structured blockchain state which includes state for value, rule, and function. Another way to look at AIN transactions is that it is the way to deliver function parameters and the results as the value state triggers the function execution. Unlike block confirmation is needed to make sure transactions are valid, transactions in AI Network can be useful even when will be executed immediately on arrival in order to ensure constant liveliness and availability.


# Structure

Below is the structure of a transaction on AIN blockchain. It largely contains 2 types of data: input from the creator and derived information.

Input from the transaction creator are:

* **nonce:** A numeric value added by the transaction creator to get a unique transaction hash. It  strictly numbers transactions to distinguish and order them. Negative nonce value means it's not a strictly ordered nonce, i.e.,  -2 means loosely ordered nonce and -1 means unordered nonce.
* **timestamp:** The unix time of transaction creation. Used only in transactions that are not strictly numbered with nonces.
* **operation:** Specifies actual state-updating request. operation can be either:
  * a single-operation with:
    * **type:** type of operation ("SET\_VALUE" | "INC\_VALUE" | "DEC\_VALUE" | "SET\_RULE" | "SET\_OWNER" | "SET\_FUNCTION")&#x20;
    * **ref:** path in the state tree to the value/rule/function hash
    * **value:** new value/rule/function hash to be set
  * a multi-operation with:
    * **type** = "SET"
    * **op\_list:** List of single operations.
      * \[ {type, ref, value}, {type, ref, value}, ..., {type, ref, value} ]
* **parent\_tx\_hash:** Identifier of parent transaction for nested transaction.

Derived data:

* **hash:** The hash of the transaction which uniquely identifies the transaction.
* **address:** Public key of the transaction creator.
* **signature:** The signature of the transaction that's used to validate the sender of the transaction. We use ECDSA and secp256k1 constants to define the elliptic curve.

When a transaction is received through a JSON RPC call, it will have 2 params. The first parameter will be the signature of the transaction by the {address}, and the second parameter will be the the transaction data object, which was used for signing. The transaction data object's properties include: nonce or timestamp, operation, and optionally, parent\_tx\_hash. A transaction's hash can be obtained by hashing the serialized the transaction object.


# Nonce

Transactions signed by the same private key (i.e., with the same address) are submitted and handled in an order using nonce. Usually, nonce is a non-negative integer value, starting from 0, that stands for the number of transactions accepted to blocks so far. Whenever a transaction is submitted its nonce is check in the following way:

* If the nonce value is equal to (the number of transactions with the same address in blocks) + 1, it's accepted
* Otherwise, it's kept in pending mode with a predefined timeout value until the condition met.

We call this type of nonce *numbered nonce*. This is enough for typical human-generated transactions. For more use cases like machine-generated transactions, we support two more types: *ordered nonce* and *unordered nonce*.

Transactions with loosely ordered nonce are ordered using timestamp:

* If the timestamp is larger than the last timestamp, it's accepted
* Otherwise, it' rejected

Transactions with unordered nonce is always accepted unless a transaction with the same transaction hash is already in blocks.

Three different types of nonce can be compared as follows:

| Type      | Nonce Field          | When To Use                                                               | Good For                                                                 | API Version |
| --------- | -------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------ | ----------- |
| Numbered  | Non-negative integer | Single client                                                             | Human-generated txs                                                      | 1.0         |
| Unordered | -1                   | Single or multiple clients, transactions are not aligned with each other. | Machine-generated txs with different generation time and submission time | 1.0         |
| Ordered   | -2                   | Multiple clients, transactions are aligned with time                      | Machine-generated txs with multiple clients                              | 1.0         |


# Read Concern

Transactions may specify read concern to indicate recommended block confirmation for the value to be valid. Even 0 confirmation can be used if the reverted operation does not cause significant flaws. For example, if the user clicked ‘like’ operation, it might be a good idea to update UI for the like count right after the interaction has happened if the broadcasted event can be accepted most of the time. In the worst case scenario, the like count shown in the UI may not be included in the block, but normally, this is not the end of the world.<br>

![](/files/-LsPy2FQhkd8Rpz7mpnv)

Fig 1. a/e/g is not included in the block state as it is recommended to be read after 1 block confirmation. read\_concern 0 does not guarantee this value will be in the block, but it still can be useful to the application which requires an immediate response. <br>

If multiple transactions try to modify the same path, only the last one is valid. For example, if tx1 is {a/b: 1} and tx2 is {a/b: 2}, the last value 2 is the one that is valid. This applies to the read\_concern as well. If tx1 is {a/b: 1, read\_concern: 1} and tx2 is {a/b: 2, read\_concern: 2}, a/b path is not recommended to be read until 2 block confirmations.<br>


# Propagation

The AIN network uses a “flood routing” protocol to ensure that transactions are propagated quickly and efficiently through the network. When validating and propagating transactions, each node in the AIN network acts as a co-equal node in a P2P network. These co-equal nodes form a mesh network, ensuring that all  nodes in the network are connected to each other at all times. When a new node connects to the AIN network, the node will establish a connection to 11 other peers in the AIN network. Connected nodes are referred to as “neighbor nodes”. Each node in the AIN network is responsible for both receiving and propagating transactions to and from each of their neighbors.

Transaction propagation begins from the originating AIN Network node which either created the transaction  or received the transaction from an AIN network client. This originating node must validate the transaction in three steps:

* Check both local transaction pool and the blockchain to make sure the transaction is not a duplicate&#x20;
* Verify that the signature contained in the transaction matches the public key of the transaction sender
* Verify nonce to check the transaction is not breaking dependency to other transactions
* Verify that the output of the transaction is valid, as determined by the AIN Network blockchain Rules

If the transaction is deemed valid, the transaction is immediately executed as a write operation to the blockchain-database. the originating node propagates the transaction to its neighbors, who repeat this validation and propagation process until each node in the network has received the transaction.<br>


# Block Structure

Structure of a block:

* Block

  * **header**
    * **epoch:** The epoch number at which the block was created.
    * **number:** The number of this block that is incremented by 1 as a new block is created. The genesis block has a block number of 0.
    * **last\_hash:** The hash of the previous block in the blockchain.
    * **last\_votes\_hash**: The hash of the last\_votes (propose, > 2/3 pre-votes and pre-commits) from validators that were used to reach consensus on the previous block.
    * **transactions\_hash**: The hash of the list of transactions that are included in the block.
    * **timestamp:** The unix timestamp for when the block was collated.
    * **proposer:** The node who created and proposed the block.
    * **size:** The size of the block.
    * **state\_proof\_hash:** The hash of the state tree.
    * **validators:** List of validators who participated in the consensus process for this block.
    * **reward:** TBD.
  * **hash:** The hash of the block's header.
  * **last\_votes:** List of validators' voting transactions (propose, pre-votes and pre-commits) that contributed to reaching consensus on the previous block. In order for a block to be added to the blockchain, it needs more than 2/3 of the signed pre-commit transactions from validators where each vote is weighted in proportion to the voter's stake.
  * **transactions:** List of transactions included in the block.
    * \[{hash, signature, transaction data}, ...]


# Account and Keys

A private key uniquely determines a single AI Network address, also known as an account.&#x20;

The usage of accounts in AI Network is more than securing funds. AI Network uses the account for allowing only certain addresses which satisfies the rule in the database path can change the value. In general,  AI Network transaction is a request to access a particular database path with a particular account, and it requires a valid digital signature to be included in the blockchain. Anyone can verify that a transaction is valid, by checking that the digital signature matches the transaction details and the account to which access is being requested.&#x20;

When a transaction is sent to the blockchain in order to change the value at a specific path in the blockchain state, it needs to be sent with a digital signature created with the private key corresponding to an account who has the permission to write the value to the path. More specifically, permission of the database path is controlled by owner and rule which can be also modified by signed transactions. While owner permission at a path is granted by specifying certain actionable types (i.e. branch\_owne&#x72;*,* write\_function, write\_owner, write\_rule) to accounts, rules are more flexible and can be used with conditional statements. The details are covered in the rules section.

The following diagrams show how an application can utilize owner and rule for managing permission of an app. At first, the application owner can start from branching its own application path, and define rules for an application at subtrees. Some of the rules at subtree may state that the data can be only written by the users themselves, and even application owner cannot modify the user data.

![](/files/-MXBsvVLYZtWWXV-mxM8)

Fig 1. (1) 0xAAAAAAAA does not have write\_owner permission at "/apps". (2) 0xAAAAAAAA has a branch permission at "/apps", so it can start a new branch "/apps/afan". (3) 0xAAAAAAAA has a write\_rule permission at "/apps/afan", so it can write rule at "/apps/afan/user0". (4) 0xBBBBBBBB does not have a write\_rule permission, so it cannot write a rule at "/apps/afan/user0".

![](/files/-MXUzsP84AEC57-4kwl3)

Fig 2. (1) 0xAAAAAAAA has permission to write the value at "/apps/afan". (2) 0xAAAAAAAA does not have permission to write the value at "/apps/afan/user0". (3) 0xBBBBBBBB has permission to write the value at "/apps/afan/user0". (4) While 0xCCCCCCCC has permission to write the value at "/apps/afan/user1", 0xBBBBBBBB does not have permission.

CAUTION: The private key must remain secret at all times. It must be backed up and protected from accidental loss. If it’s lost, it cannot be recovered and the funds and data secured by it are lost forever too.\
\ <br>


# Consensus

## Consensus on AI Network

AI Network's consensus algorithm is a version of [Tendermint](https://tendermint.com/docs/introduction/what-is-tendermint.html#consensus-overview)'s consensus algorithm with a modification that it's driven by rules. Like Tendermint, the process consists of 5 states and messages that validator nodes pass to each other that trigger state transitions. Nodes that stake AIN are called validators and one of the validators is selected to be the proposer of the next block. Proposer selection is done through evaluating the built-in proposer rule that uses the list of validators and their stakes as well as the current time to ensure that the process doesn't halt and will start a new round with the next candidate when the designated proposer is not reliable. Each validator has a chance to be a proposer with the probability proportional to its stake.

In Propose state, the selected proposer creates a block and broadcasts it to other validators. When broadcasting a block, a proposer not only sends the block but also writes the block's hash to the global state tree. If the proposal block is received within BLOCK\_CREATION\_INTERVAL and is verified, the validators accept it and move on to the Pre-vote state. If a block isn't received in time, new round begins with a new proposer selected. Once enough validators pre-vote on a block and the sum of their stakes reach the 2/3 threshold (at least the nodes who are staking 2/3 of the total stakes agree on the block), they start the Pre-commit state. Again this state requires 2/3 pre-commits to Commit to the block, which is the final state, and the process loops back to the Propose state.

Below is a state machine diagram of AIN Consensus algorithm, with related parts of the global state tree shown for a better understanding.

![](/files/-LtsByeSCb6A-w7owdyh)

We plan to refine our consensus algorithm as AIN blockchain expands. One of the ways to do so is allowing each shard of the network to establish its own consensus rules within its community as AIN evolves and multiple shards are formed. We call this concept "configurable permissions and consensus protocols", and are planning to incorporate it into AIN in the future.&#x20;

Being able to configure its own consensus gives an application the power to appropriately prioritize and de-prioritize the three properties of a blockchain– scalability, security and decentralization. If an application needs scalability, it can maximize its throughput with simpler consensus rules. If an application needs more security, it can achieve stronger security by configuring permission-less Proof of Stake (PoS) rules. If an application is striving for more decentralization, it can simply adopt new consensus rules. There is no consensus lock-in so no forking will be required. Configurable consensus will make AIN inherently flexible and help the ecosystem adapt and grow as the requirements change.


# Scalability

An application in AI Network may generate millions of transactions and many of them are not directly related to other applications. If full nodes maintain one giant tree, it can grow very large. AI Network blockchain solves scalability issue by partitioning the global state tree into several sub-tree states.<br>

There are three areas of scaling: data scaling, computation scaling, and state scaling. While the most of EVM based blockchains have to deal with all three areas and suffers from sharding them, AI Network blockchain can be only concerned with the state sharding because blockchain’s responsibility is limited to state management only. In AI Network blockchain, data and computation are managed off-chain, and computation is triggered by the state change. The state is a tree structure, which can be easily partitioned.

### **Sharding**

A shard in AIN blockchain maintains a subset of the global state tree. Each of the multiple shards is processed on a separate small blockchain instance, thus greatly increasing a blockchain’s total throughput.

Each shard validates a small part of the transaction history. It is known that POW consensus algorithm can’t be used in conjunction with sharding. This is because the computation power required to attack a shard is significantly less than the computing power required to attack the entire blockchain. Thus proof of stake (PoS) consensus algorithms are used for each shard, and only designated nodes who is authorized to commit their stakes are allowed to participate in block validation.&#x20;

The state tree is partitioned into relevant subtree and transactions for the subtree are recorded in a child block. Once the child blocks are branched out from the parent blocks, the small headers of child blocks have to be recorded on the main chain.

### **Branch and report**

For forking shard chains from the parent chain, a child first records branch transaction into the parent chain. Branch transaction includes the subtree path it wants to be in charge and the rules for reporting block headers as the new chain grows. After the branch transaction included in the parent chain, validators in the child chain are responsible for processing transactions regarding data for subtree state. The branch transaction creates a new genesis block for the child chain which includes the consensus rule for managing the new branch. When the proposer of the child chain broadcast the new block, the proposer generates report transaction for recording the header of the block into the parent chain. The child block can generate one report transaction per block while the parent block can include multiple report transactions from different shards.\ <br>

![](https://lh6.googleusercontent.com/KNpcqWlVnCL7ngxddoyiqyHUWQIjLlCMEkTbvLHybnfoaiYRe0ZcJQejk40hfqKIbXJ1aBVfVJgfzfbwJjzQ0nl8zbk7eBN4aVM_Wcuc1M4Po_B9a2Ctb1cMyfbh6EWv7zL39kg6)

**Fig 1. The diagram shows how the child state is branched from the root chain. After the branch, the child paths are managed by the child chain and only the header hash is recorded in the root state.**<br>

![](https://lh4.googleusercontent.com/lXPGuT8kcXDEXpJqzKfuC2hfztITU3y6mFm5cBwDR8bXyXM4E1QG0J7JmZcgA_s9MxdoQ36_6kSd-1dBJKPLCp--VNlQfOIuPwLfxzFMbZJAME00im9_qwC8hT-VHM3l3JJQm1dg)

**Fig 2. The diagram shows how multiple children can report to the parent block. The branch can be recursive. For example, child 1-1 is a child of child 1 which is the child of the root.**<br>


# Apps

Since AIN Blockchain is essentially a large public decentralized database, we have designed a concept of "Apps", where each app could represent a service or an organization.

## Registration

An App can be created and registered by setting app configs at `/manage_app/${appName}/create/${key}`. App configs include admin, billing, and service configs.&#x20;

#### Options

* \[boolean] is\_public: When is\_public option is set to `true`, the created app will allow anyone to set value and give branch\_owner, write\_function, and write\_rule owner permissions to anyone at the app's path (`/apps/${appName}`). Note that this option does not override the admin / billing / service configs, but sets additional permissions on top of the given configs.

## Configuration

### Admin Config

Admin config is a mapping of address and boolean (true), and if an address is added as an admin, upon the creation of the app, the address obtains all the owner permissions (branch\_owner, write\_function, write\_owner, write\_rule) as well as the write rule permission for the path `/apps/${appName}`.

```javascript
ain.db.ref(`/manage_app/${appName}/create/${Date.now()}`).setValue({
  admin: {
    "0xADDR_1": true,
    "0xADDR_2": true
  }
});
```

### Billing Config

The billing config specifies the names of the billing accounts associated with the app and the addresses that can use the billing accounts when sending transactions.

```javascript
ain.db.ref(`/manage_app/${appName}/create/${Date.now()}`).setValue({
  admin: {
    "0xADDR_1": true,
    "0xADDR_2": true
  },
  billing: {
    billingAccountA: {
      users: {
        "0xADDR_1": true,
        "0xADDR_2": true
      }
    },
    billingAccountB: {
      users: {
        "0xADDR_1": true,
        "0xADDR_3": true
      }
    }
  }
});
```

### Service Config

The service config contains service-specific configurations. For example, if the app uses a staking service, it could set the default lock-up duration by setting the config as follows:

```javascript
ain.db.ref(`/manage_app/${appName}/create/${Date.now()}`).setValue({
  admin: {
    "0xADDR_1": true,
    "0xADDR_2": true
  },
  billing: {
    billingAccountA: {
      users: {
        "0xADDR_1": true,
        "0xADDR_2": true
      }
    },
    billingAccountB: {
      users: {
        "0xADDR_1": true,
        "0xADDR_3": true
      }
    }
  },
  service: {
    staking: {
      lockup_duration: 2592000000 // ms
    }
  }
});
```

###


# Developer Guide


# Quick Start

This guide will introduce you to the core concepts for building on the AIN blockchain. By the end of this guide, you'll learn how to build a blockchain app that chats with a bot and earn 100 AIN!

{% hint style="info" %}
All examples are in this [GitHub repo](https://github.com/ainblockchain/quickstart)—clone and try them out!
{% endhint %}

## Step 1. Install SDK

To interact with the blockchain in server-side JavaScript environments like Node.js, you can use the official [blockchain SDK for JavaScript](https://github.com/ainblockchain/ain-js). Install the SDK with npm or your preferred package manager. Make sure to install version **1.10.0 or later** for full compatibility:

```
npm install @ainblockchain/ain-js@latest
```

## Step 2. Connect to blockchain

### Public RPC endpoints

The AI Network provides public RPC endpoints for blockchain interaction on both testnet and mainnet. Use testnet to debug and test performance before deploying to mainnet. To use the [SDK](https://github.com/ainblockchain/ain-js) on mainnet, set the [Chain ID](https://docs.ainetwork.ai/ain-blockchain/ai-network-design/network-id-and-chain-id) to 1.

| Network | RPC Endpoint                       | Event Handler Endpoint            | Chain ID |
| ------- | ---------------------------------- | --------------------------------- | -------- |
| Testnet | <https://testnet-api.ainetwork.ai> | wss\://testnet-event.ainetwork.ai | 0        |
| Mainnet | <https://mainnet-api.ainetwork.ai> | wss\://mainnet-event.ainetwork.ai | 1        |

```js
const Ain = require('@ainblockchain/ain-js').default;

const ain = new Ain('https://testnet-api.ainetwork.ai', 'wss://testnet-event.ainetwork.ai', 0); // testnet
const ain = new Ain('https://mainnet-api.ainetwork.ai', 'wss://mainnet-event.ainetwork.ai', 1); // mainnet
```

## Step 3. Create your wallet

You can create multiple accounts and set a default account. However, it’s crucial to **back up your private key** and store it securely. Losing your private key may result in losing access to your account permanently. Take extra precautions to prevent unauthorized access!

{% code title="create\_account.js" %}

```js
const Ain = require('@ainblockchain/ain-js').default;

const ain = new Ain('https://testnet-api.ainetwork.ai', 'wss://testnet-event.ainetwork.ai', 0);

// create new account
const accounts = ain.wallet.create(1);
const address = accounts[0];

// set the new account as the default account
ain.wallet.setDefaultAccount(address);

// print the default account
console.log(ain.wallet.defaultAccount);

// example output:
// {
//   address: '0x09A0d53FDf1c36A131938eb379b98910e55EEfe1',
//   private_key: '...',
//   public_key: '...'
// }
```

{% endcode %}

## Step 4. Get AIN (for free!)

### Testnet: Free AIN via Faucet

You can receive 100 AIN daily for free on the Testnet through our faucet.

1. Go to the [faucet site](http://faucet.ainetwork.ai).
2. Enter the address created in **Step 3**.
3. Click "Request for testing" to get your AIN.

![The AI Network Faucet site.](/files/-LwDq1C0dPu6JaKgDY4r)

You can view transaction details by copying the transaction hash (starting with 0x…) and searching it on the [AI Network Testnet block explorer](https://testnet-insight.ainetwork.ai/).

![The AI Network Faucet site.](/files/-LwDrBjla5PyYO1Wth2j)

### Mainnet: Native AIN via AIN DAO Bot

👉 [Join the AIN DAO Discord](https://discord.com/invite/aindao)

To convert **ERC-20 AIN** from Ethereum to **Native AIN** on the AI Network, follow these steps:

#### Step 1: Import $AIN Tokens into MetaMask

1. Open MetaMask and go to “Assets”.
2. Click “Import Token” → “Custom Token”.
3. Use this contract address: `0x3a810ff7211b40c4fa76205a14efe161615d0385`
4. Click “Add Custom Token” to view your $AIN balance.

#### Step 2: Deposit $AIN to AIN DAO Discord

1. In Discord, type `/ain deposit` to receive your unique deposit address (start with `0x...`).
2. Copy the deposit address.
3. Open your ETH wallet and locate the $AIN token.
4. Click “Send,” paste the deposit address, and input the amount to deposit (minimum: 500 AIN).
5. Confirm the transaction.
6. In Discord, type `/ain balance` to confirm your balance.

#### Step 3: Withdraw AIN Credits to Native AIN

1. Use the `/ain withdraw` command in Discord.
2. Enter your AI Network wallet address.
3. Specify the withdrawal amount (minimum: 500 AIN).
4. Confirm the transaction.

## Step 5. Create your app

{% hint style="warning" %}
You need at least 5 AIN to create an app. See **Step 4** to get AIN.
{% endhint %}

You can create your own app by setting a value to `/manage_app/${appName}/create/${key}` path. The value must contain an [admin config](https://docs.ainetwork.ai/ain-blockchain/ai-network-design/apps#admin-config), which is an object of `{ [address]: true }`. The addresses in the admin config will get the owner and write permissions to the `/apps/${appName}` path.

Setting a value at the path `/manage_app/${appName}/create/${key}` triggers the native function `_createApp`, automatically setting the `owner` and `rule` permissions.

{% code title="create\_app.js" %}

```js
const Ain = require('@ainblockchain/ain-js').default;

const ain = new Ain('https://testnet-api.ainetwork.ai', 'wss://testnet-event.ainetwork.ai', 0); // testnet

// import the account using private key from Step 3
const address = ain.wallet.addAndSetDefaultAccount('YOUR_PRIVATE_KEY');

// define a unique app name
// the app name can only contain lowercase letters, numbers, and underscores(_)
// rename if write rule error occurs
const appName = 'YOUR_APP_NAME';
const appPath = `/apps/${appName}`;

// create an app at /apps/${appName}
// the admin config below grants 'address' both owner and write permissions for the app
ain.db
  .ref(`/manage_app/${appName}/create/${Date.now()}`)
  .setValue({
    value: {
      admin: {
        [address]: true,
      },
      service: {
        staking: {
          lockup_duration: 604800000, // 7d in ms
        },
      },
    },
    nonce: -1,
  })
  .then((res) => {
    console.log('tx_hash:', res.tx_hash);
    console.log('code:', res.result.code); // 0: success
  });
```

{% endcode %}

You can use the `getOwner` function to check app's owner permissions and confirm the app was created successfully.

{% code title="create\_app.js" %}

```js
// check the owner permissions have been set properly
ain.db
  .ref(appPath)
  .getOwner()
  .then((res) => {
    console.log(JSON.stringify(res, null, 2));

    // example output:
    // {
    //   ".owner": {
    //     "owners": {
    //       '0x09A0d53FDf1c36A131938eb379b98910e55EEfe1': {
    //         "branch_owner": true,
    //         "write_function": true,
    //         "write_owner": true,
    //         "write_rule": true
    //       }
    //     }
    //   }
    // }
  });
```

{% endcode %}

## Step 6. Stake AIN to your app

{% hint style="warning" %}
On the mainnet, a free tier is available for staking, so this step is optional. However, if you want to write more data, you need to stake AIN.
{% endhint %}

Staking is important for securing the capacity needed to write data to the blockchain. The amount of data you can record is proportional to the amount of AIN you have staked. Below is a simple code example on how to set up staking.

{% code title="stake\_app.js" %}

```js
const Ain = require('@ainblockchain/ain-js').default;

const ain = new Ain('https://testnet-api.ainetwork.ai', 'wss://testnet-event.ainetwork.ai', 0); // testnet

// import the account using private key from Step 3
const address = ain.wallet.addAndSetDefaultAccount('YOUR_PRIVATE_KEY');

const appName = 'YOUR_APP_NAME'; // use the app name from Step 5
const appPath = `/apps/${appName}`;

ain.db
  .ref(`/staking/${appName}/${address}/0/stake/${Date.now()}/value`)
  .setValue({
    value: 50,
    nonce: -1,
  })
  .then((res) => {
    console.log('tx_hash:', res.tx_hash);
    console.log('code:', res.result.code); // 0: success
  });
```

{% endcode %}

## Step 7. Make your app public

To allow others (e.g., an echo bot) to write to your app’s paths, you need to modify the rules. By default, the write rule is:

```js
{
  ".rule": {
    "write": "auth.addr === '${address}'"
  }
}
```

This means only your account can write data.

To make the app public (allowing anyone to write data), change the write rule to `true`. Use the `setRule` function to update it.

{% code title="set\_rule.js" %}

```js
const Ain = require('@ainblockchain/ain-js').default;

const ain = new Ain('https://testnet-api.ainetwork.ai', 'wss://testnet-event.ainetwork.ai', 0); // testnet

// import the account using private key from Step 3
const address = ain.wallet.addAndSetDefaultAccount('YOUR_PRIVATE_KEY');

const appName = 'YOUR_APP_NAME'; // use the app name from Step 5
const appPath = `/apps/${appName}`;

// set write rules to allow anyone to write data
ain.db
  .ref(appPath)
  .setRule({
    value: {
      '.rule': {
        write: true,
      },
    },
    nonce: -1,
  })
  .then((res) => {
    console.log('tx_hash:', res.tx_hash);
    console.log('code:', res.result.code); // 0: success
  });
```

{% endcode %}

Now, anyone can use your app! You can check the rule with `getRule` function.

#### Advanced settings ✨

If you’re concerned about security (which you should be), you can define more specific paths and rules.\
For example, you can restrict access to `/apps/my_app/restricted/area/for/0xabcd...1234` so that only the holder of the private key for `0xabcd...1234` can write to it. Notice the use of wildcards for flexibility!

```js
ain.db.ref('/apps/my_app/restricted/area/for/$address').setRule({
  value: {
    '.rule': {
      write: `auth.addr === '$address'`,
    },
  },
  nonce: -1,
});
```

## Step 8. Set up event listener

You can register an event listener by setting a function config to a specific path.

{% code title="set\_function.js" %}

```js
const Ain = require('@ainblockchain/ain-js').default;

const ain = new Ain('https://testnet-api.ainetwork.ai', 'wss://testnet-event.ainetwork.ai', 0); // testnet

// import the account using private key from Step 3
const address = ain.wallet.addAndSetDefaultAccount('YOUR_PRIVATE_KEY');

const appName = 'YOUR_APP_NAME'; // use the app name from Step 5
const appPath = `/apps/${appName}`;

const functionPath = `${appPath}/messages/$user_addr/$timestamp/user`; // wild cards!

// set a function to be triggered when writing values at the function path
ain.db
  .ref(functionPath)
  .setFunction({
    value: {
      '.function': {
        'my-bot-trigger': {
          function_type: 'REST',
          function_url: 'http://testnet-echo-bot.ainetwork.ai/trigger', // function url for testnet
       // function_url: 'http://mainnet-echo-bot.ainetwork.ai/trigger', // function url for mainnet
          function_id: 'my-bot-trigger', // use your own function id
        },
      },
    },
    nonce: -1,
  })
  .then((res) => {
    console.log('tx_hash:', res.tx_hash);
    console.log('code:', res.result.code); // 0: success
  });
```

{% endcode %}

Once registered, a POST request will be sent to the `function_url`, whenever a value is written to `/apps/my_bot/messages/$user_addr/$timestamp/user` path. Since `my-bot-trigger` is just a placeholder, customize it with your own trigger name.

You can check the function was set successfully using the `getFunction` function.

Below is an example of a triggering value (at .../user) and a response value (at .../echo-bot) written by Echo bot. If configured correctly, the Echo bot will respond to your message by writing a value automatically.

```js
// '/apps/<app-name>/messages/<user-addr>/<timestamp>'
{
  "user": "Hello!",
  "echo-bot": "Did you mean \"Hello!\"?"
}
```

## Step 9. Write values

Everything is ready! You can now write data with the `setValue` function to trigger the Echo bot function. Use the `getValue` function to check the response value.

{% code title="set\_value.js" %}

```js
const Ain = require('@ainblockchain/ain-js').default;

const ain = new Ain('https://testnet-api.ainetwork.ai', 'wss://testnet-event.ainetwork.ai', 0); // testnet

// import the account using private key from Step 3
const address = ain.wallet.addAndSetDefaultAccount('YOUR_PRIVATE_KEY');

const appName = 'YOUR_APP_NAME'; // use the app name from Step 5
const appPath = `/apps/${appName}`;

const userMessagePath = `${appPath}/messages/${address}`;

// set a value at the path to trigger the function
ain.db
  .ref(`${userMessagePath}/${Date.now()}/user`)
  .setValue({
    value: 'Hello!',
    nonce: -1,
  })
  .then((res) => {
    console.log('tx_hash:', res.tx_hash);
    console.log('code:', res.result.code); // 0: success
  });

// check that the value is set correctly
// if the echo bot is alive, it should have responded to your message
ain.db
  .ref(userMessagePath)
  .getValue()
  .then((data) => {
    console.log(JSON.stringify(data, null, 2));

    // example output:
    // {
    //   "1631691438245": {
    //     "user": "Hello!",
    //     "echo-bot": "Did you mean \"Hello!\"?" // written by the echo bot.
    //   }
    // }
  });
```

{% endcode %}


# AI Network Products


# AI Network Worker

This guide will instruct you on how to set up a worker node on the AI Network.

**\[CAUTION] AI Network Worker on AIN Blockchain is on beta.**

You can provide your machine's computing power to the decentralized applications on AI Network Blockchain through AI Network Worker.

## How To Run AIN Worker

### Requirements

* Docker
* Ubuntu 18.04 or above
* Minimum Storage Requirements: 50 GB
* If you want to provide GPU computing power,
  * GPU
  * Nvidia-docker

### 1. (Optional) Check Graphics Driver

Before running a GPU supported worker, you should check the requirements. **If you want to run non-GPU worker, please skip this part.** First, let's check if the graphics driver is installed correctly. Please enter the following command:

```
$ nvidia-smi
```

The results will be printed in the following form, and you can check the CUDA version supported by your driver.

```
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 450.80.02    Driver Version: 450.80.02    CUDA Version: 11.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla K80           Off  | 00002DE1:00:00.0 Off |                    0 |
| N/A   44C    P0    69W / 149W |      0MiB / 11441MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```

If the driver is not installed or the supported CUDA version is lower than 10.1, refer to [here](/ain-blockchain/developer-guide/tools/ai-network-worker#install-graphic-driver) to install the graphics driver.

### 2. (Optional) Check Nvidia Docker

**If you want to run non-GPU worker, please skip this part.** The next step is to check whether the docker and Nvidia docker is installed, which allows you to utilize the GPU on docker containers. Please enter the following command:

```
$ sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi
```

After you run the above command, you should see something similar to this:

```
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 450.80.02    Driver Version: 450.80.02    CUDA Version: 11.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla K80           Off  | 00002DE1:00:00.0 Off |                    0 |
| N/A   44C    P0    69W / 149W |      0MiB / 11441MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```

If you're having trouble with the installation, please refer [here](/ain-blockchain/developer-guide/tools/ai-network-worker#install-nvidia-docker) to install the Nvidia docker.

### 3. Start a Worker

#### Non-GPU Worker

```shell
docker run -l AinConnect.container=master -d \
--restart unless-stopped --name ain-worker
-e APP_NAME=collaborative_ai \
-e NAME={NAME} \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $HOME/ain-worker/{NAME}:/root/ain-worker/{NAME} \
ainblockchain/ain-worker
```

#### GPU Worker

```shell
docker run -l AinConnect.container=master -d \
--restart unless-stopped --name ain-worker --gpus all
-e APP_NAME=collaborative_ai \
-e NAME={NAME} \
-e CONTAINER_GPU_CNT=1 \
-e GPU_DEVICE_NUMBER=0 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $HOME/ain-worker/{NAME}:/root/ain-worker/{NAME} \
ainblockchain/ain-worker
```

#### Configurable Parameters

<table><thead><tr><th width="251.20151792692485">Parameter Name</th><th width="332.30795431298645">Description</th></tr></thead><tbody><tr><td><code>NAME</code></td><td>Worker Name</td></tr><tr><td><code>APP_NAME</code></td><td>AI Network Blockchain APP Name<br>(ex. collaborative_ai)</td></tr><tr><td><code>CONTAINER_VCPU</code></td><td>(Optional) Container CPU Core. Default is 1.</td></tr><tr><td><code>CONTAINER_MEMORY_GB</code></td><td>(Optional) A Container memory capacity in GB <br>Default is 4.</td></tr><tr><td><code>DISK_GB</code></td><td>(Optional) DISK Capacity in GB. Default is 50.</td></tr><tr><td><code>CONTAINER_GPU_CNT</code></td><td>(Optional) A Container Number of GPUs</td></tr><tr><td><code>GPU_DEVICE_NUMBER</code></td><td>(Optional) GPU Device IDs separated <code>,</code> <br>(ex. <code>0</code>, <code>0,1</code>, ...)</td></tr><tr><td><code>CONTAINER_MAX_CNT</code></td><td>(Optional) The maximum number of containers. Default is 1.</td></tr><tr><td><code>MNEMONIC</code></td><td>(Optional) if it does not exist, it is automatically created and saved in <code>$HOME/ain-worker/{NAME}/env.json</code></td></tr></tbody></table>

#### Officially Supported App List

* collaborative\_ai

### 4. Terminate a Worker

To terminate the AIN Worker, enter the following command:

```shell
docker rm -f $(docker ps -f "label=AinConnect.container" -q -a)
```

## Appendix

### Install Graphics Driver

Let's install the Nvidia graphics driver. The graphics driver's version must be at least 418.39. Execute the following commands in order:

```bash
$ sudo apt-get update -y
$ sudo apt purge nvidia-*
$ sudo add-apt-repository ppa:graphics-drivers/ppa
$ sudo apt update
```

You can find the appropriate driver version in the following way:

```bash
$ sudo apt install ubuntu-drivers-common
$ ubuntu-drivers devices
...
vendor   : NVIDIA Corporation
model    : GK210GL [Tesla K80]
driver   : nvidia-driver-440-server - distro non-free
driver   : nvidia-driver-390 - distro non-free
driver   : nvidia-driver-410 - third-party free
driver   : nvidia-driver-415 - third-party free
driver   : nvidia-driver-418-server - distro non-free
driver   : nvidia-driver-455 - third-party free recommended
driver   : nvidia-driver-450-server - distro non-free
driver   : nvidia-driver-450 - distro non-free
driver   : xserver-xorg-video-nouveau - distro free builtin
...
```

Find the version tagged 'recommended' in the list of drivers. In the example above, `nvidia-driver-455` is tagged with 'recommended'. Now you can install the appropriate graphics driver with the following command.

```
// Change `455` to the number that recommended for your system.
$ sudo apt install nvidia-driver-455
```

After installation is complete, reboot the system.

```bash
$ sudo reboot
```

Use the `nvidia-smi` command to confirm that the driver installation was successful.

```bash
$ nvidia-smi

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 450.80.02    Driver Version: 450.80.02    CUDA Version: 11.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla K80           Off  | 00002DE1:00:00.0 Off |                    0 |
| N/A   44C    P0    69W / 149W |      0MiB / 11441MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```

### Install Nvidia Docker

When the graphic driver installation is completed, you need to install the Nvidia docker to run AIN Worker. This guide has been created by referring to the Nvidia docs: <https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker>

First, run the following command to install docker.

```bash
$ curl https://get.docker.com | sh \
  && sudo systemctl start docker \
  && sudo systemctl enable docker
```

After that, install the Nvidia container toolkit.

```bash
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
   && curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - \
   && curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
```

Finally, after installing the Nvidia docker, restart the docker.

```bash
$ sudo apt-get update
$ sudo apt-get install -y nvidia-docker2
$ sudo systemctl restart docker
```

Nvidia docker installation is complete. To check if it's installed properly, run the command below and make sure you see an output similar to the following.

```bash
$ sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 450.51.06    Driver Version: 450.51.06    CUDA Version: 11.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla T4            On   | 00000000:00:1E.0 Off |                    0 |
| N/A   34C    P8     9W /  70W |      0MiB / 15109MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```

##


# AI Network Insight

AI Network Insight([insight.ainetwork.ai](https://insight.ainetwork.ai)) is an Explorer for AI Network’s Blocks and its Blockchain Database. AI Network Insight allows users to monitor and explore transaction data and block data in the AI network.&#x20;

## Features and Components

### Menu

<img src="/files/-LpfTZH0zkfkO5dUSG0x" alt="" data-size="original">

The AI Network Insight menu bar allows users to browse and explore information from the AI Network.

* **Home:** shows an overview of essential AI Network information.
* **Database:** shows data in the AI Network blockchain database in a tree-structured format.
* **Transactions:** shows information on AI Network transactions.
* **Blocks:** shows information on blocks created by AI Network's Blockchain Nodes.
* **Nodes:** shows information about Blockchain Nodes on the AI Network.

### Search

<img src="/files/-LpfSkBgwbh_mxrejbuT" alt="" data-size="original">

The AI Network search bar in the top-right corner allows users to search for information about account, transactions and blocks. The accepted search keyword types and formats are as follows:

* **Address**

  * 42 characters long
  * Starts with a prefix `0x`
  * Hexadecimal numbers only \[0\~9, a\~f]

* **Transaction Hash**

  * 66 characters long
  * Starts with a prefix `0x`
  * Hexadecimal numbers only \[0\~9, a\~f]

* **Block**
  * Decimal numbers only \[0\~9]

Invalid search keywords, or searches which return no results will result in an error page.

### Network selector

<img src="/files/-Lpfs2j8BNS-2oMU_LDh" alt="" data-size="original">

Users can select a network to view using the dropdown menu located below the search bar.&#x20;

## Home <a href="#home" id="home"></a>

The Home page gives users an an overview of information from the AI Network. This information includes block height, 24h-average block generation time, current price of AIN coin, 14-day transaction history, and 24-hour TPS(transactions per second) history.

### **Network status**

* **Block Height:** shows how many blocks have been created since the genesis.
* **24-hour average block time:** shows the average time for generating a new block over the last 24 hours
* **AIN price:** shows the latest price of AIN coin. The exchange rate is from GOPAX (as of Sep. 2019).

![](/files/-LpfLKP-8Yrf-L6wWsdF)

* **14-day transaction history:** displays a graph of the daily number of transaction trends over the last 14 days. You can find today's number of transactions above the graph by default. If you move your mouse and hover over a date, the number of transactions for that date is displayed as below.
* **24-hour TPS history:** displays a graph of hourly average TPS(Transactions Per Second) over the last 24 hours. You can find the latest average TPS above the graph by default. If you move your mouse and hover over a time, the TPS of that time is displayed as below.

![](/files/-LpfKt6aKn_e19JXMZga)

###

### Blockchain node

AI Network Insight also provides information on the blockchain nodes. You can find the address of a node, the number of blocks a node proposed and validated, the location of a node, the amount of AIN coins a node staked, and the amount of AIN coins a node has been rewarded over the last 24 hours. A lot of this information is related to the PoS (Proof-of-Stake) consensus protocol used by the AI Network blockchain. By default, this section allows you to see the top 10 nodes sorted by the amount of staked AIN coin. Click the 'View all' button on the upper-right of the list to view information on all nodes. Detailed descriptions of each column can be found at **Blockchain Node Details**

![](/files/-LpfLlyrFR3apXNDx-5r)

###

### Latest Blocks & Transactions

The essential information of the latest blocks and transactions can be found at the bottom of the Home section. For more details, click the number of a Block or a Tx (Transaction) Hash. Click the 'View all' button on the upper-right of each list in order to see the whole list. A detailed description of each column can be found at **Block Details** and **Transaction Details**.

![](/files/-LpfM1_QuiJf2ZAnFx2D)

## Transactions

All executed transactions are listed here. &#x20;

![](/files/-LpkBMMxcR5HJhulFzzB)

Clicking a Tx Hash link opens a separate page, detailing all information for the Tx Hash.

![](/files/-LpkMpFDhi57hhbYS6kk)

### Tx Hash / Transaction Hash

Tx Hash stands for transaction hash.  These Tx Hashes act as unique IDs for  each transaction. Since Tx Hashes are  66-character-long-strings, the middle part of a Tx Hash string is abbreviated as '...' for easier readability.

* Example:&#x20;
  * Original Tx Hash:\
    0x310530808edd44c7b3f2c890f06115dc2f23ad137dca73f0b287e69576775d76
  * Abbreviated Tx Hash:\
    0x3105...5d76

### Status

Status lets you know if a transaction is successfully included in a block and if the block has been confirmed as added to the blockchain. There are three possible statuses:

* **Success:** The transaction has passed the related [rule](https://ai-network.gitbook.io/ai-network/ai-network-design/state-rules-and-functions/rules), executed, correctly ordered with other transactions, and has been included in a confirmed block block on the blockchain.
* **Pending:** The transaction is in the transaction pool, or there is some network issue(e.g. network latency)
* **Fail:** The transaction has failed validation and will not be included in the blockchain. This can happen for the following reasons:
  * In case of failing to pass the rule.
  * In case of wrong ordering.
  * In case of an invalid nonce.

### Block no.

This is the number (or height) of the block on the blockchain containing the transaction. In the list view, an icon notifying an error appears  if the transaction is not successfully included in any block. In the detail view window, the number of blocks that have been confirmed since the transaction is displayed.

### Time

Gives time information on when a transaction was created.&#x20;

### From / To

The addresses of who sent and received the transaction. Click the address to see more details of the account.

### Triggered by

A transaction can be triggered by another transaction. This is the hash of the triggering transaction. This will remain empty if the transaction has not been triggered by any other transaction.

For example,

1. User1 can assign a  machine learning job to peer1.
2. After peer1 completes the job, the job data is written to the database database via transactions.
3. When all job data has been written to the database, this may result in a 'job-done' transaction, which can be sent to the network to indicate that peer1 has completed their work.
4. This "job-done" transaction confirms the result, and indicates that AIN coin payment should be sent to  peer1.
5. This payment transaction is triggered by the 'job-done' transaction.
6. The job is complete.

### Nonce

The number of the transaction added by the transaction creator to get a unique transaction hash.&#x20;

For more information, click [here](https://ai-network.gitbook.io/ai-network/ai-network-design/transactions/nonce).

### Operation

Specifies the type of database state-updating request. Operations consists of following components.

* **Op:** stands for operator. It sets and updates data or performs functions on the designated path.&#x20;
* **Path:** refers to the path in the blockchain database where data is being updated.
* **Value:** is used for the operator as a parameter. It could be a simple numeric or text value, or a lengthy function code.
* **Raw data:** shows the original data contained in the transaction. Op, Path, and Value are parsed from this.&#x20;

For more information, click [here](https://ai-network.gitbook.io/ai-network/ai-network-design/transactions/operations).

## Blocks

All created blocks are listed here. &#x20;

![](/files/-Lq-YQEwuvm-GHjovMay)

Clicking a block number link opens a up a new page giving more detailed information on the block.

![](/files/-Lq-YkERS51tlSlRgfex)

### Block number

Block number is also known as block height. It tells you the number of blocks that came before a block.

### Time

Tells users when a block was proposed.

### Block Hash

Unique identifier of the block.

### Parent Hash

Unique identifier of the previous block.

### Proposer

The address of the node who proposed the block.

### Validators

List of validator addresses who participated in the consensus process for this block. Click the purple number of nodes to see the list of validators.

### Reward

The number of AIN coins rewarded for forging the block.

### Size

The size of the block in bytes.

### Transactions

List of transactions included in the block.

## Nodes

All blockchain nodes of AI Network are listed here. &#x20;

![](/files/-Lq0Rb2yvI2SArVcylNv)

Clicking an address of a node opens a new page give more detailed information on that node.

![](/files/-Lq0RiRYwUNLFu65CofF)

### Address

Unique address of the node.

### Location

The country location for each node is determined according to the nodes IP address. It may be null if the node does not want to reveal their location, or if the IP address is unknown.

### Staked / Rewarded

The amount of staked and rewarded AIN. Staking AIN is required for any node to be a validator. Among all the validators, one single proposer is chosen to propose a block at each height of the blockchain. This proposer will be rewarded with AIN coin. The probability of being a proposer is proportional to the node's stake.&#x20;

For more details of consensus algorithm and staking, click [here](https://ai-network.gitbook.io/ai-network/ai-network-design/consensus).

### No. of Proposed / Proposed Blocks

The number and the list of  blocks proposed by a node. Click a block number for detailed information of the proposed block in the Proposed Blocks list.

### No. of Validated / Validated Blocks

The number and the list of blocks validated by a node. Click a block number for detailed information on the validated block in the Validated Blocks list.

## Database

shows data stored in blockchain database of AI Network in a tree-structured format.&#x20;

![](/files/-Lq3fBMauxPawmzSfyxl)

###

### Database Tree

Expand or collapse a node by clicking a button with '+' or '-' icon. By expanding a node, lower-level nodes or properties of the node are revealed.&#x20;

![](/files/-Lq3gwkzUtcMAgkxevKZ)

### Database Details

Click a name of a node to see detailed information on the node.

![](/files/-Lq3l7uq3DzZYbTVUG2H)

* **Address:** On the upper side of the page, the address of the node is shown. All database nodes in the AI Network have their own url.
* **Breadcrumb:** is used as a navigational aid in exploring the AI Network Database. Click a purple node name link to see breadcrumb details.
* **Properties:** are displayed with property names and their values. If there are subordinate properties, an option to expand appears in front of the property name.
* **Highlights:** are shown on changed, added, deleted, or moved properties. If you want to see the latest highlights, click the 'Refresh' button on the upper-right corner.
* **Rules:** are javascript expressions which dictate which transactions are valid and accepted for the node. For more details, click [here](https://ai-network.gitbook.io/ai-network/ai-network-design/state-rules-and-functions/rules).&#x20;


# Testnet Server Node

A Testnet node is available at [`testnet-api.ainetwork.ai`](https://testnet-api.ainetwork.ai). Feel free to send API calls to this node, but note that Testnet node cluster is in field tests so it can be re-deployed or re-started any time without notice.


# Ainize Trigger

### Welcome!

This tutorial explains the process of calling the API of a project deployed in Ainize using AI Network Blockchain. Here, we will intro the process of writing down the results from the model after setting the Trigger Function on Blockchain using the API of the model that was fine-tuned (GPT-2) with the novel Pride and Prejudice.

AI Network Blockchain, which can handle large-scale transactions, has been designed to securely record communications between clients as well as sending requests and nodes processing tasks. A more detailed description of AI Network Blockchain can be found [here](https://docs.ainetwork.ai/).

#### You will learn to:

1. Create an App on the AI Network Blockchain and register a Trigger Function through Ainize
2. Use the Trigger Function
3. Write Values on AI Network Blockchain

### Learn by following the steps!

**GitHub Repository**

* <https://github.com/ainize-team/ainize-trigger-tutorial>

**Ainize**

* [https://ainize.ai/ainize-team/ainize-trigger-tutorial](https://ainize.ai/ainize-team/ainize-trigger-tutorial?branch=main)


# Project user

Let's find out how to create an App on AI Network Blockchain and set up the Trigger Function through Ainize.

#### (1) Create your own app

First, let's create an App.

![](/files/Wplc0aMKSD2pOcy1f5jU)

When creating an app, the `/manage_app/${appName}` Database path will appear as shown in the picture above. This means that the user who created the app has been registered as the admin of the app. The admin will get owner and writing permissions in the `/apps/${appName}` path. (You can check the following picture in detail on [AI Network Insight](https://insight.ainetwork.ai/))

![](/files/yc51CGSljya3na5UAHEL)

#### (2) Set a Trigger Function

Now, let’s register the Trigger Function. When a value is written in a specific path set as the `Database path`, a POST request is sent to the endpoint set as the `API endpoint`, including the value written to the path.

![](/files/DACXJvADB41lGTIIitAe)

#### (3) Test Trigger Function (optional)

Let's check if the Trigger Function has been set correctly. First, input the path and value you want to write down and click the Test trigger button. When this button is clicked, the value entered as Input will be written in the `Database path`. When the value is written, the trigger function set in step 2 will be triggered and a POST request will go to the `API endpoint`. After creating the result value in the API Server deployed on Ainize, the result value will be written on the blockchain.

![](/files/yJU27VqjZchP3XVgqdgP)

When you click the “Go to check result” button, you can see the blockchain, like in the following picture, and you will be able to see that the values are written correctly.

![](/files/5IrhrIr8PUNxwmfSAxXt)

To summarize the flow:

![](/files/1l2fB1xURmEplnIalwte)


# Project deployer

Let's find out how to handle the requests made by writing values on a specific path set by the project user.

#### (1) Install ain-py

First of all, let’s install ain-py. [ain-py](https://pypi.org/project/ain-py/) is a Python SDK used to interact with AI Network blockchain. It can be installed through PyPI.(We used version 0.1.4 in this tutorial.)

```bash
# if your server is node js server, use ain-js
# npm install @ain-blockchain/ain-js
pip install ain-py==0.1.4
```

#### (2) Import package

Then, import the packages that we will use in the tutorial.

```python
import os
import json
import logging
import asyncio
import torch
from ain.ain import Ain
from flask import Flask, request
from ain.types import ValueOnlyTransactionInput
from transformers import GPT2LMHeadModel, GPT2Tokenizer
```

`ain` : Package used to interact with AI network.

`asyncio` : Package for asynchronous programming. Used with `ain`.

`flask` : Package for web framework. Used to create API servers.

`transformers` : Package for dealing with natural language processing.

#### (3) Connect to a blockchain node

In this step, let’s connect with the blockchain node. `PROVIDER_URL` can contain the URL of AI Network's Test Net (<https://testnet-api.ainetwork.ai/>), Main Net (<https://mainnet-api.ainetwork.ai/>)).

To use ain-py on Main Net, `chainId` must be set to 1 (Test Net: 0, Main Net: 1)

```python
PROVIDER_URL = os.environ['PROVIDER_URL']
# if use testnet, set chainId to 0
ain = Ain(PROVIDER_URL, chainId=1)
```

#### (4) Set an account

If you are connected to the blockchain node, use the account's private key to set up your account. When deploying the project to Ainize, the environmental variable `AINIZE_INTERNAL_PRIVATE_KEY` will be automatically set. `addAndSetDefaultAccount` is a function that adds an account from a private key that enters the parameter and sets the account as the default account.

```python
AINIZE_INTERNAL_PRIVATE_KEY = os.environ['AINIZE_INTERNAL_PRIVATE_KEY']
ain.wallet.addAndSetDefaultAccount(AINIZE_INTERNAL_PRIVATE_KEY)
```

#### (5) Set values

At this point, everything should be ready! When a request comes in to the server, it will get the result value and write the result value on the AI Network Blockchain.

When a value is written in the specific path set by the project user, the trigger function will be triggered and a request will be sent to the registered endpoint.

```python
res = json.loads(request.data.decode('utf-8'))
print(res)
# {
#     "function": {
#         "function_id": "gpt2-pride-and-prejudice",
#         "function_type": "REST",
#         "function_url": "<https://main-ainize-trigger-tutorial-scy6500.endpoint.ainize.ai/trigger>"
#     },
#     "transaction": {
#         "address": "Oxbb5ecD24E8Bf0937d8c22D4440Fa95D50a1d108E",
#         "extra": {
#             "created_at": 1640223741870,
#             "executed_at": 1640223741870
#         },
#         "hash": "Oxeeb009260026a0fb030aa4218104ec2acecbed8c8cf4dba31650c1509cc2b0a1",
#         "signature": "Oxeeb009260026a0fb030aa4218104ec2acecbed8c8cf4dba31650c1509cc2b0a1a1dfa59513aac069f4a389e925cc885ae7b3ae7f8e1e2483603c555eb34288152c7b2b4ab774553cfe5f2761d16507fe500ea862ad0b34e52b436f5a91afa5cbib",
#         "tx_body": {
#             "nonce": -1,
#             "operation": {
#                 "is_global": false,
#                 "ref": "/apps/ainize_tutorial/Oxbb5ecD24E8Bf0937d8c22D4440Fa95D50a1d108E/1640223741870/user",
#                 "type": "SET_VALUE",
#                 "value": "{
#                     "baseText": "I love him. He's not proud. I was wrong. I was entirely wrong about him.",
#                     "len": 50
#                 }"
#             },
#             "timestamp": 1640223741430
#         }
#     }
# }
```

First, let's check if the incoming request is valid. We need to check if `transaction` , `tx_body`, `operation` are among the parameters of the request.

```python
if (not res.get('transaction') or
        not res['transaction'].get('tx_body') or
        not res['transaction']['tx_body'].get('operation')):
    return f'Invalid transaction : {res}', 400
transaction = res['transaction']['tx_body']['operation']
tx_type = transaction['type']
if tx_type != 'SET_VALUE':
    return f'Not supported transaction type : {tx_type}', 400
```

If the incoming request is valid, put the requested `value` into the model to get the result value and write the result value to the blockchain. To write a value to the blockchain, you need to use setValue of ain-py (but async was used to process it asynchronously). `path` contains the path to write the value, and `value` contains the value to write in the path.

```python
# path = /apps/appName/path/to/your/want
async def set_value(path, value):
    result = await ain.db.ref(path).setValue(
        ValueOnlyTransactionInput(
            value=value,
            nonce=-1
        )
    )
```

```python
value = eval(transaction['value'])
# Get the result by putting baseText and len as input to the model
result = make_story(value['baseText'], value['len'])
try:
    # Delete the 'user' of the ref to make the result_ref 
    # like /apps/appName/.../result
    result_ref = transaction['ref'].split('/')[:-1]
    result_ref.append('result')
    result_ref = '/'.join(result_ref)
    print(result_ref)
    # /apps/ainize_tutorial/Oxbb5ecD24E8Bf0937d8c22D4440Fa95D50a1d108E/1640223741870/result
    asyncio.run(set_value(result_ref, result))
except Exception as e:
    logging.error(f'setValue failure : {e}')
    return f'setValue failure : {e}', 500
return '', 204
```

You can see that the results are written correctly on the AI Network Blockchain.

![](/files/xQYmnLYMEDYOL4VOUN9O)


# Why do we have to use Ainize Trigger?

Those of you who have experienced Ainize Trigger may think, “Why should I call Endpoint through the blockchain if I can send a request directly to Endpoint?” To tell the difference, we need to talk about Web 3.0.

The Internet today does not have an independent state. From the user's point of view, stateless is like using the Internet for the first time in a new browser (without browsing history, autocomplete, favorites, etc.), every time you use the Internet. Imagine you are using the Internet in a new environment every time you use the Internet. It would be very inconvenient.

Cookies were first developed to solve these problems. A cookie is an information file that is recorded on a user's computer through the server that the site uses when a user visits a site. This allows you to save states such as access history, autocomplete, favorites, and more. The problem with cookies, however, is that they are created and controlled by the service provider (the site you visit), not the user. Users do not have access/modification rights to their states.

![7 Types of Internet Cookies | Everything You Should Know](/files/Y99ftkqaaX1tvuyka9m4)

The second developed method is to manage the user's state on the service provider's central machine. This type of Internet is called Web 2.0. Web 2.0 is the Internet that has been used for the past 20 years, and social networks and content sharing are the basis for this. The most distinctive feature is the emergence of massive, centralized platforms. There are platforms such as Facebook, Amazon, Netflix, and Google, which have billions of states. These are Internet companies that have grown to the point where they can exert great power not only on the Internet but also on society in general.

In this era, the basic direction of Web 3.0 is the decentralization movement to share the states, the online power concentrated in a few large companies, to everyone, without being monitored or being inspected. This can be implemented by blockchain.

If you use blockchain, you can solve the above problems. If you create an app through blockchain, you can manage your own state, and everyone participating in the blockchain can manage and utilize these states, rather than being monopolized by some companies. But in the case of API calls, how can we record states? AI Network allows you to leave a state.

AI Network supports event listeners. When a state is written in the blockchain database, an event listener is triggered to send a POST request to the endpoint registered in advance, and the state value is written to the database. Not only can you manage these states, but other users can also access them. A stateless API (Web 2.0) has changed into a stateful API (Web 3.0)! Therefore, by using Ainize Trigger, you can create your own App on the AI Network, which saves the state so that static information, as well as programs that move, change and react, can also be connected over the Internet!

![](/files/2p2cT4LvOcg5EVCm2Lwc)


# Token Bridge

Please note that the AI Network token bridge between AIN native coins and AIN ERC20 tokens on Ethereum is currently purely conceptual.

**Base Bridge: If you are looking for the Base network bridge instead, please visit** [**bridge.ainetwork.ai**](https://bridge.ainetwork.ai)**.**

> ***Please contact <info@ainetowork.ai> before proceeding.*** The code below contains deprecated elements and may no longer function correctly. It is intended for expert users and partner developers who possess a detailed understanding of the AIN blockchain architecture and its underlying mechanics.

\
This guide assumes that you have an Ethereum wallet with some AIN ERC20 tokens in it. You can buy AIN ERC20 tokens on Uniswap, Balancer, or GOPAX.

#### AIN ERC20 Token Addresses

* Mainnet: [0x3A810ff7211b40c4fA76205a14efe161615d0385](https://etherscan.io/address/0x3a810ff7211b40c4fa76205a14efe161615d0385)
* Testnet (ropsten): [0xB16c0C80a81f73204d454426fC413CAe455525A7](https://ropsten.etherscan.io/address/0xB16c0C80a81f73204d454426fC413CAe455525A7)

#### AIN Native Token Pool Addresses

* Mainnet
  * Ethereum: [0x00CC50B6DC70cC854B1231272FDe0b0CFE561d72](https://etherscan.io/address/0x00CC50B6DC70cC854B1231272FDe0b0CFE561d72)
  * AI Network: [0x00CC0491CdA2dA91385C9c424852Ae096B7AbD89](https://insight.ainetwork.ai/accounts/0x00CC0491CdA2dA91385C9c424852Ae096B7AbD89)
* Testnet
  * Ethereum: [0x00AA9daA2aC950fF445B435Af7F6c39C5c65D677](https://ropsten.etherscan.io/address/0x00aa9daa2ac950ff445b435af7f6c39c5c65d677)
  * AI Network: [0x00AA7d797FB091AF6dD57ec71Abac8D2066BE298](https://testnet-insight.ainetwork.ai/accounts/0x00AA9daA2aC950fF445B435Af7F6c39C5c65D677)&#x20;

## Check-in

Here, a check-in refers to a transfer of your AIN ERC20 tokens on Ethereum to AI Network as AIN native coins.

### 1. Send your AIN ERC20 tokens to the AI Network ERC20 Token Pool address.

#### 1-1. Using a MetaMask, Add AIN ERC20 Token to your list of tokens.

![1. Click import tokens](/files/RxvifivWxjcuO2AOMrR9) ![2. Enter the AIN ERC20 address](/files/Xhkvo6I1gLx5lzjJemcW) ![3. Click Import Tokens](/files/I7lvvpANSeowfTIfZgnv)

#### 1-2. Send AIN ERC20 to AI Network ERC20 Token Pool.

AI Network ERC20 Token Pool address

* Mainnet: [0x00CC50B6DC70cC854B1231272FDe0b0CFE561d72](https://etherscan.io/address/0x00CC50B6DC70cC854B1231272FDe0b0CFE561d72)
* Testnet: [0x00AA9daA2aC950fF445B435Af7F6c39C5c65D677](https://ropsten.etherscan.io/address/0x00aa9daa2ac950ff445b435af7f6c39c5c65d677)

:warning:Make sure you are on the right network (Ethereum Mainnet vs Ropsten Test Network) before sending your assets.

There is no minimum/maximum amount you need to check-in.

![1.Click send](/files/SwHwsBiH5wUJFnlHfdJo) ![2. Enter the AI Network ERC20 Token Pool address](/files/roJfBoP9veWCNoaksWLY) ![3. Confirm](/files/pqG8Unn4x6cbQzW2Q8L3)

#### 1-3. Make sure the transaction is successfully executed.

You can view your transaction on Etherscan by clicking the transaction on MetaMask and then "View on block explorer".

![Click View on block explorer to see your transaction on Etherscan.](/files/7jmV3hdqIbdQW78oeGgO)

### 2. Send a check-in request transaction to the AI Network blockchain.

{% code title="check-in-mainnet.js" %}

```javascript
/* This code snippet is for Mainnet! */
const stringify = require('fast-json-stable-stringify');
const Accounts = require('web3-eth-accounts');
const Ain = require('@ainblockchain/ain-js').default;
const ain = new Ain('https://mainnet-api.ainetwork.ai', 1); // chainId = 1 (mainnet)
const ethAccounts = new Accounts();
const ainErc20TokenAddress = '0x3A810ff7211b40c4fA76205a14efe161615d0385';
​
// Create 1 new account
const accounts = ain.wallet.create(1);
// WARNING: Make sure to record this private key somewhere safe! We cannot retrieve it for you!
console.log(JSON.stringify(ain.wallet.accounts, null, 2));
const myAddress = accounts[0];
ain.wallet.setDefaultAccount(myAddress);
// Or, import an account you already have
// const myAddress = ain.wallet.addAndSetDefaultAccount(YOUR_PRIVATE_KEY);

// Create a sender proof with your Ethereum key (sender)
const timestamp = Date.now();
const ref = `/checkin/requests/ETH/1/${ainErc20TokenAddress}/${myAddress}/${timestamp}`;
// Should be exactly the same as the AIN ERC20 token you sent in Step 1-2.
const amount = 20000;
// Sender is the Ethereum address that you used to send AIN ERC20 token in Step 1-2.
const sender = 'YOUR-ETHEREUM-ADDRESS';
const senderPrivateKey = 'YOUR-ETHEREUM-PRIVATE-KEY';
const senderProofBody = {
  ref,
  amount,
  sender,
  timestamp,
  nonce: -1,
};
const senderProof = ethAccounts.sign(ethAccounts.hashMessage(stringify(senderProofBody)), senderPrivateKey).signature;

// Send a check-in request
ain.db.ref(ref)
  .setValue({
    value: {
      amount,
      sender: myAddress,
      sender_proof: senderProof,
    },
    nonce: -1,
    gas_price: 500,
    timestamp: timestamp // Should be the same as the checkinId in ref
  })
  .then((res) => {
    console.log(JSON.stringify(res, null, 2));
  });
```

{% endcode %}

{% code title="check-in-testnet.js" %}

```javascript
/* This code snippet is for Testnet! */
const stringify = require('fast-json-stable-stringify');
const Accounts = require('web3-eth-accounts');
const Ain = require('@ainblockchain/ain-js').default;
const ain = new Ain('https://testnet-api.ainetwork.ai', 0); // chainId = 0 (testnet)
const ethAccounts = new Accounts();
const ainErc20TokenAddress = '0xB16c0C80a81f73204d454426fC413CAe455525A7';
​
// Create 1 new account
const accounts = ain.wallet.create(1);
// WARNING: Make sure to record this private key somewhere safe! We cannot retrieve it for you!
console.log(JSON.stringify(ain.wallet.accounts, null, 2));
const myAddress = accounts[0];
ain.wallet.setDefaultAccount(myAddress);
// Or, import an account you already have
// const myAddress = ain.wallet.addAndSetDefaultAccount(YOUR_PRIVATE_KEY);

// Create a sender proof with your Ethereum key (sender)
const timestamp = Date.now();
const ref = `/checkin/requests/ETH/3/${ainErc20TokenAddress}/${myAddress}/${timestamp}`;
// Should be exactly the same as the AIN ERC20 token you sent in Step 1-2.
const amount = 20000;
// Sender is the Ethereum address that you used to send AIN ERC20 token in Step 1-2.
const sender = 'YOUR-ETHEREUM-ADDRESS';
const senderPrivateKey = 'YOUR-ETHEREUM-PRIVATE-KEY';
const senderProofBody = {
  ref,
  amount,
  sender,
  timestamp,
  nonce: -1,
};
const senderProof = ethAccounts.sign(ethAccounts.hashMessage(stringify(senderProofBody)), senderPrivateKey).signature;

// Send a check-in request
ain.db.ref(ref)
  .setValue({
    value: {
      amount,
      sender,
      sender_proof: senderProof,
    },
    nonce: -1,
    gas_price: 500,
    timestamp: timestamp // Should be the same as the checkinId in ref
  })
  .then((res) => {
    console.log(JSON.stringify(res, null, 2));
  });
```

{% endcode %}

### 3. Check that your AI Network account's balance has increased on Insight.

You can check your AI Network account's balance at the AI Network blockchain explorer.

* Mainnet: <https://insight.ainetwork.ai/accounts/${YOUR-AIN-ADDRESS}>
* Testnet:  <https://testnet-insight.ainetwork.ai/accounts/${YOUR-AIN-ADDRESS}>

## Check-out

Similarly, a check-out refers to a transfer of your AIN native coins on AI Network to Ethereum as AIN ERC20 tokens.

### 1. Send a check-out request transaction to the AI Network blockchain.

For check-out's, there is a minimum and a maximum allowed per request as well as a maximum per day for the entire network. Currently the limits are:

* Minimum check-out amount per request: 10,000 AIN
* Maximum check-out amount per request: 100,000 AIN
* Maximum check-out amount per day for the network: 1,000,000 AIN

```javascript
/* This code snippet is for Mainnet! */
const Ain = require('@ainblockchain/ain-js').default;
const ain = new Ain('https://testnet-api.ainetwork.ai', 1); // chainId = 1 (mainnet)
const ainErc20TokenAddress = '0x3A810ff7211b40c4fA76205a14efe161615d0385';
​
// Import an account you created in the check-in process
const myAddress = ain.wallet.addAndSetDefaultAccount(YOUR_PRIVATE_KEY);

// Send a check-in request
const timestamp = Date.now();
const ref = `/checkout/requests/ETH/1/${ainErc20TokenAddress}/${myAddress}/${timestamp}`;
const amount = 10000;
// This is the Ethereum address that will receive the AIN ERC20 tokens
const recipient = 'YOUR-ETHEREUM-ADDRESS';
ain.db.ref(ref)
  .setValue({
    value: {
      amount,
      recipient,
      fee_rate: 0.001
    },
    nonce: -1,
    gas_price: 500,
    timestamp: timestamp // Should be the same as the checkoutId in ref
  })
  .then((res) => {
    console.log(JSON.stringify(res, null, 2));
  });
```

```javascript
/* This code snippet is for Testnet! */
const Ain = require('@ainblockchain/ain-js').default;
const ain = new Ain('https://testnet-api.ainetwork.ai', 0); // chainId = 0 (testnet)
const ainErc20TokenAddress = '0xB16c0C80a81f73204d454426fC413CAe455525A7';
​
// Import an account you created in the check-in process
const myAddress = ain.wallet.addAndSetDefaultAccount(YOUR_PRIVATE_KEY);
​
// Send a check-in request
const timestamp = Date.now();
const ref = `/checkout/requests/ETH/3/${ainErc20TokenAddress}/${myAddress}/${timestamp}`;
const amount = 10000;
// This is the Ethereum address that will receive the AIN ERC20 tokens
const recipient = 'YOUR-ETHEREUM-ADDRESS';
ain.db.ref(ref)
  .setValue({
    value: {
      amount,
      recipient,
      fee_rate: 0.001
    },
    nonce: -1,
    gas_price: 500,
    timestamp: timestamp, // Should be the same as the checkoutId in ref
  })
  .then((res) => {
    console.log(JSON.stringify(res, null, 2));
  });
```

### 2. Check that your transaction was successfully added to the blockchain on Insight.

You can view your transaction at:

* Mainnet: <https://insight.ainetwork.ai/transactions/${txHash}>
* Testnet: <https://testnet-insight.ainetwork.ai/transactions/${txHash}>

### 3. Check that your Ethereum wallet has received AIN ERC20 tokens.

You can confirm your increased AIN ERC20 token balance on either MetaMask or Etherscan.

* Mainnet: <https://etherscan.io/address/${ethereumAddress}>
* Testnet: <https://ropsten.etherscan.io/address/${ethereumAddress}>


# Trouble Shooting

This document provides troubleshooting guidance when using the AIN Blockchain.

### Exeeded Free tier budget.

Error message

```
Exceeded state budget limit for free tier (42479668 > 25000000)
```

You need to stake AIN token to your app if you want to write more data. [How to stake](https://docs.ainetwork.ai/ain-blockchain/developer-guide/getting-started#step-8.-stake-ain-to-your-app)

You can manage your app data capacity to using garbage collection rule.

```javascript
const txBody = {
  operation: {
    typeL 'SET_RULE',
    ref: `/apps/${appName}/PATH_TO_SET_GC_RULE`
    value: {
      ".rule": {
        state: {
          gc_max_siblings: 50,
          gc_num_siblings_deleted: 10, // You should set this over 10.
        },
      }
    },
    gas_price: 500,
    timestamp: Date.now(),
    nonce: -1,
  }
}
```


# Developer Reference


# Blockchain API


# JSON RPC API

For the Blockchain JSON RPC APIs, see: <https://github.com/ainblockchain/ain-blockchain/blob/develop/JSON_RPC_API.md>&#x20;


# Node Client API

For the Blockchain Node Client APIs, see: <https://github.com/ainblockchain/ain-blockchain/blob/develop/README.md#blockchain-node-client-api-for-development-and-testing-purposes>


# Blockchain SDK


# ain-js

[ain-](https://pypi.org/project/ain-py/)[js](https://www.npmjs.com/package/@ainblockchain/ain-js) is a JavaScript (or TypeScript) SDK for interacting with AIN Blockchain.&#x20;

Github: <https://github.com/ainblockchain/ain-js>&#x20;

Docs: <https://ainblockchain.github.io/ain-js/>&#x20;


# ain-py

[ain-py](https://pypi.org/project/ain-py/) is a python SDK for interacting with AIN Blockchain.&#x20;

Github: <https://github.com/ainblockchain/ain-py>&#x20;

Docs: [https://ainblockchain.github.io/ain-py/](https://ainblockchain.github.io/ain-py/ain.html)&#x20;


# Validators

This guide will instruct you on how to set up a validator node on the AI Network.

:warning: Warning: You may earn rewards by running validators, but if you get slashed by your mistake, you can lose your money and reputation.

### Validator Parameters

* Annual reward rate: \~8% + transaction fees (varies)
* Unbonding period: 7 days
* Payout frequency: Every block (\~20 seconds)

## Initial Set-up

### Requirements

#### Minimum stake requirements

None for validators without proposal rights. If you'd like to run a proposer node, contact us at <info@ainetwork.ai>.

#### Hardware requirements

* 16 CPUs
* 64GB Memory
* 2TB Disk (SSD preferably)
* Example GCP Instance: c2-standard-16

#### Networking requirements

* Reserve a static, publicly routable IPv4 IP address for your node.
* Your firewalls should expose TCP/5000 and TCP/8080

#### OS requirements

* Ubuntu 18.04 or above

## Running a Validator

While AI Network is in beta testing mode, we're only allowing whitelisted nodes to participate as validators. Please contact <info@ainetwork.ai> if you're interested.

1\. Git clone & install dependencies

```
git clone https://github.com/ainblockchain/ain-blockchain.git
cd ain-blockchain
yarn install
```

2\. Start a node

* Using a keystore file

```
BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/mainnet-prod \
    STAKE=10000 \
    ACCOUNT_INJECTION_OPTION=keystore \
    KEYSTORE_FILE_PATH=/path/to/keystore/file \
    nohup node --max-old-space-size=55000 client/index.js >/dev/null 2>error_logs.txt &
```

* Using a mnemonic phrase

```
BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/mainnet-prod \
    STAKE=10000 \
    ACCOUNT_INJECTION_OPTION=mnemonic \
    nohup node --max-old-space-size=55000 client/index.js >/dev/null 2>error_logs.txt &
```

3\. Inject your account into your node

* Using a Keystore file

  The following command requires two inputs: the path of your Keystore file and its password.

```
node inject_account_gcp.js <NODE_ENDPOINT_URL> --keystore
```

* Using a mnemonic phrase

  The following command requires two inputs: a mnemonic phrase and an account index. If you do not enter an account index, it is set to the default value of 0.

```
node inject_account_gcp.js <NODE_ENDPOINT_URL> --mnemonic
```

4\. Check out your node on the blockchain explorer!

<https://insight.ainetwork.ai/nodes/${yourNodeAddress}>

{% embed url="<https://insight.ainetwork.ai/nodes>" %}

## Running a Validator with Docker

Instead of starting from a git clone, you can use a pre-built docker image from [Docker Hub](https://hub.docker.com/repository/docker/ainblockchain/ain-blockchain).

1\. Pull Docker image from Docker Hub

```
docker pull ainblockchain/ain-blockchain:latest
```

2\. Run Docker image

* Using a Keystore file

```
docker run -e ACCOUNT_INJECTION_OPTION=keystore \
    -e SYNC_MODE=peer -e STAKE=10000 -e SEASON=mainnet \
    --network="host" -d ainblockchain/ain-blockchain:latest
```

* Using a mnemonic phrase\
  If you executed the second command, you don't need to manually inject your account into your node.

```
docker run -e ACCOUNT_INJECTION_OPTION=mnemonic \
    -e SYNC_MODE=peer -e STAKE=10000 -e SEASON=mainnet \
    --network="host" -d ainblockchain/ain-blockchain:latest
    
docker run -e ACCOUNT_INJECTION_OPTION=mnemonic -e MNEMONIC="your mnemonic" \
    -e SYNC_MODE=peer -e STAKE=10000 -e SEASON=mainnet \
    --network="host" -d ainblockchain/ain-blockchain:latest
```

3\. Inject your account into your node

* Using a Keystore file\
  The following command requires two inputs: the path of your Keystore file and its password.

```
node inject_account_gcp.js <NODE_ENDPOINT_URL> --keystore
```

* Using a mnemonic phrase

  The following command requires two inputs: a mnemonic phrase and an account index. If you do not enter an account index, it is set to the default value of 0.

```
node inject_account_gcp.js <NODE_ENDPOINT_URL> --mnnemonic
```

4\. Check out your node on the blockchain explorer!

<https://insight.ainetwork.ai/nodes/${yourNodeAddress}>

{% embed url="<https://insight.ainetwork.ai/nodes>" %}


# Staking

## What is staking?

Staking is a way to lock your tokens to help the blockchain network or applications run smoothly. In return, you may earn rewards or contribute to the stability of the system. Think of it like putting your money in a savings account: you're helping the system grow, and sometimes you earn interest.

## How does staking work?

In our system, staking works a bit differently depending on where you stake your tokens:

1. **Staking in the consensus app**

* **What it does:** AIN Blockchain adopts the PoS consensus algorithm. The staking amount in the 'consensus' app is used to create new blocks on the blockchain.
* **What you get:** You earn rewards based on the blocks created.
* **Why it's important:** It secures the blockchain and keeps it running smoothly.

2. **Staking in other apps**

* **What it does:** Your tokens provide the resources needed to write data to the blockchain.
* **What you get:** Rewards depend on the app developer's decision. Some apps may offer rewards, while others may not.
* **Why it's important:** It keeps the apps functional and contributes to the ecosystem.

## How is this different from other blockchain?

* In other blockchain, you lock your tokens to help the network and earn rewards like new tokens or fees.
* In our blockchain, you can do more:
  1. **Earn rewards:** By staking in the consensus app, you earn rewards for block production.
  2. **Support apps:** By staking in other apps, you support their operations with rewards depending on the app developer's choice.

This gives you the choice to either focus on earning rewards or supporting the ecosystem.

## How to stake?

In our system, there are two main methods to stake your tokens: using [ain-js](https://github.com/ainblockchain/ain-js) or [blockchain tools](https://github.com/ainblockchain/ain-blockchain/blob/master/tools/staking/sendStakeTx.js). Both methods are straightforward and easy to use.

### Method 1: Using ain-js

1. Install ain-js Make sure you have Node.js and ain-js installed.

```sh
$ npm install @ainblockchain/ain-js
```

2. Stake your tokens

Use the following example code to connect to the blockchain and stake tokens:

{% code title="stake\_app.js" %}

```js
const Ain = require('@ainblockchain/ain-js').default;

const ain = new Ain('https://testnet-api.ainetwork.ai', 'wss://testnet-event.ainetwork.ai', 0); // testnet

const address = ain.wallet.addAndSetDefaultAccount('YOUR_PRIVATE_KEY');

const appName = 'YOUR_APP_NAME'; // or 'consensus
const appPath = `/apps/${appName}`;
const amount = 10; // amount of tokens to stake

ain.db
  .ref(`/staking/${appName}/${address}/0/stake/${Date.now()}/value`)
  .setValue({
    value: amount,
    nonce: -1,
  })
  .then((res) => {
    console.log('tx_hash:', res.tx_hash);
    console.log('code:', res.result.code); // 0: success
  });
```

{% endcode %}

3. Confirm the transaction

### Method 2: Using blockchain tools

If you prefer a simpler, non-programming method, you can use the **pre-built script** available in our repository.

1. Download the repository

```sh
$ git clone https://github.com/ainblockchain/ain-blockchain.git
$ cd ain-blockchain/tools/staking
```

2. Set up the environment Make sure you have Node.js installed. Install any dependencies by running:

```
$ npm install
```

3. Run the staking script Use the provided [sendStakeTx.js](https://github.com/ainblockchain/ain-blockchain/blob/master/tools/staking/sendStakeTx.js) script to stake your tokens:

```sh
$ node sendStakeTx.js <BLOCKCHAIN_API_ENDPOINT> <CHAIN_ID> <APP_NAME> <STAKING_AMOUNT> <ACCOUNT_TYPE> [<KEYSTORE_FILE_PATH>]
$ node sendStakeTx.js https://testnet-api.ainetwork.ai 0 test_app 100 private_key
$ node sendStakeTx.js https://testnet-api.ainetwork.ai 0 test_app 100 mnemonic
```

* Replace the placeholders with your own values:
* `<BLOCKCHAIN_API_ENDPOINT>`: The endpoint of the blockchain API. (e.g. testnet: '<https://testnet-api.ainetwork.ai>', mainnet: '<https://mainnet-api.ainetwork.ai>')
* `<CHAIN_ID>`: The ID of the chain. (0: testnet, 1: mainnet)
* `<APP_NAME>`: The name of the app.
* `<STAKING_AMOUNT>`: The amount of tokens to stake.
* `<ACCOUNT_TYPE>`: The type of the account: private\_key, mnemonic, keystore
* `<KEYSTORE_FILE_PATH>`: The path to the keystore file.

4. Confirm the transaction

## How to decide the staking amount?

To determine the right staking amount for your app, consider the following key points:

1. Understand resource needs

* Your app requires two budgets:
  * **Bandwidth Budget:** Calculated as the number of the DB write operations needed to execute the transaction.
  * **State Budget:** Based on the memory used in the blockchain's state tree.
* The more resources your app uses, the higher the staking amount required.

2. Dynamic allocation

* The amount of state budget your app receives depends on the percentage of total staking your app contributes to the systam.
* This allocation is dynamic and adjusts as the total staking changes across all apps.

3. Use [JSON RPC API](https://github.com/ainblockchain/ain-blockchain/blob/master/JSON_RPC_API.md#ain_getstateusage): Get State Usage

* Run the `getSateUsage` method to check:
  * Your app's current state usage.
  * Available resources based on your app's staking amount. (in the free tier, you can only use 5% of the total state budget)
* Example command: Request:

```sh
curl https://testnet-api.ainetwork.ai/json-rpc -X POST -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "ain_getStateUsage",
  "params": {
    "protoVer": "1.1.3",
    "app_name": "YOUR_APP_NAME"
  }
}'
```

Response:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "result": {
      "usage": {
        "tree_height": 6,
        "tree_size": 11,
        "tree_bytes": 2114,
        "tree_max_siblings": 5
      },
      "available": {
        "tree_height": 30,
        "tree_bytes": 12291542508.778091,
        "tree_size": 76822140.67986308
      },
      "staking": {
        "app": 50500000,
        "total": 10168575.540000014,
        "unstakeable": 50500000
      }
    },
    "protoVer": "1.1.3"
  }
}
```

Interpret the response:

* State Usage (usage)
  * tree\_bytes: Your app is currently using `2114` bytes of state budget.
* Available State (available)
  * tree\_bytes: You can use up to `12291542508.778091` bytes of state budget.
* Staking Details (staking)
  * app: Your app has staked `50500000` tokens.
  * total: The total staking amount in the system is `10168575.540000014` tokens.

4. How to decide staking

* If `usage.tree_byte` is close to `available.tree_bytes`, your app is nearing its limit.
* Increase your staking amount of `app` to get more state budget.
* Keep monitoring the state usage to ensure your app has enough resources.


# What is AIN DAO

## Mission

The AIN DAO is a Decentralized Autonomous Organization (DAO) that governs the AI Network ecosystem. Our mission is to build a network that makes AI accessible for everyone to share and collaborate anywhere in the world in real time. We believe collaboration is the future of AI, and together, we will achieve the world’s largest network of GPUs, models, and data.

## Roles

An NFT membership is required to access AIN DAO and participate in its governance. (i.e., decision-making, proposing new initiatives, voting).

We have three roles for our members to choose from based on the individual traits and skills they can use to contribute to the AIN DAO. Members will choose their roles, and depending on the member’s level of expertise, they will be assigned from Level 1 to Level 5 following a level sorting system. I.e., Scholar Level 1, Creator Level 3, etc.

The roles are:

* Captains: 👨⚓🌊 Ahoy! Every ship should have a good captain! Captains are members who can provide resources to AIN DAO, such as RUNO holders, investors, and sponsors.
* Creators: ​🎨​🖼💎​ Drop your best AI Creation! Creators are members of AIN DAO with skills in AI and NFT creation.
* Scholars: ​💻​👨‍💻​ 👩🏻‍🎓 It's all about the Algorithm! Scholars are developers and researchers of open-source AI-related projects (formerly known as Ainizers) and blockchain developers.
* Citizens: 🚶🚶🏾‍♀️🌎 Just passing by! Citizens are non-members who are not skilled enough to take a role but are interested in learning or getting to know more about AIN DAO. Since Citizens are non-members, they will always be considered to be Level 0.

> If you're interested in joining AIN DAO, please fill out this [form](https://docs.google.com/forms/d/1byA4y83zjZ_AICnoDWnRNHzHNgK6PFuyJpwKtyj_0Vs)!

## Roadmap

Coming soon!


# Runo (Run Your Node)

RUNO NFT is essential for building AI collaboration infrastructure. GPUs sold by RUNO are used as materials for GPU Sponsorship.

Runo is a node NFT character of the AI Network blockchain project. Runo NFT holders can use Runo to provide computing resources to the AI Network mainnet, and receive daily AIN token rewards. In addition, Runo is a dynamic NFT that levels up and evolves according to the node's operating period. If you want to participate in an AI Network project that creates an Internet infrastructure for artificial intelligence and metaverse in the Web3 era, buy Runo NFT and keep collecting AIN tokens.&#x20;

<figure><img src="/files/qNYkmeR049e2leErEVRt" alt="" width="340"><figcaption></figcaption></figure>

## Early Adopters Earn More&#x20;

The earlier you mint, the better! Runo NFTs minted earlier will let you earn more $AIN than Runo NFTs minted later!&#x20;

## Stronger Node, More AIN&#x20;

Runo NFT has three node types: High GPU, GPU, and CPU. High GPU Runo has the highest performance and brings the most AINs. Buy the type of Runo that you want with AIN.

## Run Longer, Higher Rarity & Profit&#x20;

The longer Runo runs, the higher the level goes. The appearance of Runo evolves as the level goes higher, which turns your NFT into an NFT with a higher rarity, enabling you to earn more AINs. Be the first to Buy the Runo NFT, and make yours evolve faster than others.

## How to Participate as a Resource Provider in an AI Network Ecosystem

Follow [AI Network Twitter](https://twitter.com/ainetwork_ai) and join [AIN DAO Discord](https://discord.com/invite/XnvtZQm6BV) for the latest updates. To see more about Runo, visit the [AI Network website](https://www.ainetwork.ai/node).&#x20;

&#x20;


# GPU Sponsorship Program

We provide collaborative GPUs to make AI more accessible to the community.

The GPU resources collected from Runo will be provided to projects that can positively impact the AI ecosystem's growth and development. It creates a connection point for a true AI collaboration infrastructure.

The allocation of resources to projects that will activate the AI Network ecosystem is determined by AIN DAO. AIN DAO is a community of people building the AI Network, an AI collaboration ecosystem. AI Network does not see AI as belonging to individuals or organizations. We believe that “AI for All” can be achieved in the true sense when AI is managed in collaboration with the community, as AI data and resources are products of social processes. This is why AI Network operates the AI collaboration ecosystem community as a DAO (decentralized autonomous organization).

AIN DAO comprises various AI experts, including resource providers (investors), researchers, developers, and AI service creators, who agree to build the AI collaboration infrastructure. Through their consensus, resource provision projects are selected, and these selected projects are given the opportunity for Runo sales for GPU sponsorship.

## How to apply to this GPU Sponsorship Program?

Please read the below slide, copy this [template](https://dao.ainetwork.ai/t/template-gpu-support-program-proposal/109/5), and submit the proposal with the details.&#x20;

{% embed url="<https://docs.google.com/presentation/d/17_wZU-FJg8HtKK_vNn-Lt6PLfJA8sSU0l5SPqgSZMdQ/edit#slide=id.g22703827eeb_0_0>" %}
**Click here to see more about GPU Sponsorship Program**&#x20;
{% endembed %}


# Onboarding & Participation

First off, welcome to AIN DAO! We're honored and pleased that you are interested in taking the journey with us.

> Our mission is to build a network that makes AI easily accessible for everyone to share and collaborate anywhere in the world in real-time. We believe collaboration is the future of AI, and together, we will achieve the world’s largest network of GPUs, models, and data.

### 1. Follow the AI Network's Twitter

> <https://twitter.com/ai__network>

...so you don't miss out on the exciting news!

### 2. Fill out the application form

> <https://forms.gle/fiRfNeM9MCM1CiBU8>

We will review and analyze the submission with a cutting-edge algorithm to create a membership NFT representing your personality, skills, and interests!

### 3. Check out your email and membership NFT

Application reviews may take up to 1 month. If you meet the requirements during the evaluation, we will issue an NFT. Please remember to check your mailbox, as we will send the evaluation results via email.

The NFT is used for verification purposes on Discord, forum, and Snapshot platforms. If your application is approved, you should get an NFT to the Ethereum address you entered in the above form.

#### NFT Collections

Members who have chosen roles will be assigned from Level 1 to Level 5 according to their expertise, milestones completed, or resources provided. The guidelines are as follows:

Captains: 👨⚓🌊&#x20;

* Level 1: Runo NFT holders&#x20;
* Level 2: Holders with 4 or more rounds of Runo, including Round 1
* Level 3: Holders who have 8 or more rounds of Runo, including Rounds 1 and 2.&#x20;
* Level 4: Only available by referral.&#x20;
* Level 5: Only available by referral.

Creators: 🎨​💵​&#x20;

* Level 1: Participants for AI Network's creators program or similar projects&#x20;
* Level 2: Accepted 4 more proposals and launch the AI services&#x20;
* Level 3: Accepted 8 more proposals and launch the AI services&#x20;
* Level 4: Only available by referral&#x20;
* Level 5: Only available by referral

Developers: 💻​👨‍💻​ 👩🏻‍🎓&#x20;

* Level 1: Participants for AI Network's developer program or similar projects&#x20;
* Level 2: Accepted 4 more proposals and deploy the AI models&#x20;
* Level 3: Accepted 8 more proposals and deploy the AI models&#x20;
* Level 4: Only available by referral&#x20;
* Level 5: Only available by referral

> [Lv1](https://opensea.io/collection/ain-dao-lv1), [Lv2](https://etherscan.io/address/0x6aac96421f5bde09273b5267270f41144f6bcbcb), [Lv3](https://opensea.io/collection/ain-dao-lv3), [Lv4](https://opensea.io/collection/ain-dao-lv4), [Lv5](https://opensea.io/collection/ain-dao-lv5)

*Note: You may need to unhide the NFT in your OpenSea profile.*

#### Hats (Roles)

There are 3 roles within AIN DAO, and the character's hat in your NFT shows which role you take on.

* Captains have a pirate hat
* Creators have a magician's hat
* Scholars have a graduation cap

Last but not least, all active participants in the AIN DAO Discord are given the "Citizen" role. They don't have hats, but they are as valued community members as others. :purple\_heart:

### 4. Head to the Discord

> <https://discord.gg/XnvtZQm6BV>

Let's dive into the DAO, then!

1. Read the rules (and follow them, please)
2. In [#roles-n-levels](https://discord.com/channels/938909864674082826/974125136720580628), select the emoji corresponding to your role
3. In [#collabland-join](https://discord.com/channels/938909864674082826/938940417628586005), connect your wallet to unlock the members-only channels

### 5. Participate in governance

* In [#governance](https://discord.com/channels/938909864674082826/938912253586051083), you can discuss new or ongoing proposals.
* The [#voting](https://discord.com/channels/938909864674082826/975587109073223710) is where the members vote on the proposals and decide whether to promote the proposal to the Snapshot.

For more information on the governance process, refer to [this page](/ain-dao/governance).


# Governance

## Process

1. Discord
   1. Propose new initiatives and make the ideas more concrete in the [#governance](https://discord.com/channels/938909864674082826/938912253586051083) channel.
   2. Note that this stage is informal, and it is not restricted to the specific channel/platform.
2. Forum
   1. Create a proposal on the [forum](https://dao.ainetwork.ai/) using the [template](https://dao.ainetwork.ai/t/template-proposal-template/51) and continue the discussion.
3. Voting Round 1 on Discord
   1. If enough alternatives are considered, and discussions are held, start a voting round on the [#voting](https://discord.com/channels/938909864674082826/975587109073223710) channel. Make sure to provide a link to the forum proposal.
4. Snapshot
   1. If the proposal gets more than 5 votes from the selected roles, it will be promoted to [Snapshot](https://snapshot.org/#/ainetwork.eth) by the Moderators.
5. Voting Round 2 on Snapshot
   1. The 2nd voting round will be anywhere from 3 to 7 days, depending on the project. Anyone with an AIN DAO Membership NFT can cast a vote.


# Tokenomics


# AI Network Tokenomics

## Overview

![](/files/EZo2e8IBHD82Wza3aTfq)

At the center of the AI Network tokenomics is $AIN. $AIN is the token that can be exchanged for decentralized computing power. AI Network obtains GPUs from the resource providers and in exchange, they get $AIN. Applications, such as Ainize and AINFTs, on AI Network, can use computing power and the blockchain as their backends, as well as decentralized storage solutions. They provide services to the users including researchers, developers, and creators. As the applications grow, their $Tokens will grow in value and $AIN as well. Since there are more demands, more resource providers will be willing to supply their GPUs, hence the flywheel spins.

## Supply and Distribution

* Total supply: 700,000,000
* [Coingecko](https://www.coingecko.com/en/coins/ai-network)
* [Uniswap](https://app.uniswap.org/#/swap?outputCurrency=0x3a810ff7211b40c4fa76205a14efe161615d0385\&chain=mainnet), [Balancer](https://app.balancer.fi/#/trade/0x6b175474e89094c44da98b954eedeac495271d0f/0x3A810ff7211b40c4fA76205a14efe161615d0385), [Gopax](https://www.gopax.co.kr/exchange/ain-krw)
* [Etherscan](https://etherscan.io/token/0x3a810ff7211b40c4fa76205a14efe161615d0385)
* More info is available on <https://ainetwork.ai/token>

## Token bridge


# AINFT Tokenomics

Overview

AI Network has developed a model for tokenomics in [AINFT](/ai-agents/ainft) projects. It focuses on the sustainable growth of the community by providing sufficient rewards to its members – especially the NFT holders – as well as growing the AI Network ecosystem along with the projects'.

![](/files/XnkroIV1NCsIcgQKErF5)

### NFT Holder Reward Mechanics

#### Activity Rewards

Users can earn $Token through activities on the project's platforms or other metaverses as part of the profit-sharing system. The treasury will decide how much of the revenue they will share with the NFT holders, buy tokens from the DEX, and deposit the tokens in the reward pool smart contract.

#### "Staking" NFTs

Users can "stake" their NFTs to boost the rewards. Note that the smart contract does not require the users to actually transfer the ownership of their NFTs at any point. They would only need to verify their ownership and select the NFTs to level up. The higher the level of the NFT you own, the more rewards it will earn.

## Relationship with $AIN

One of the key functionalities of this token economy framework is increasing the usage of $AIN. The $Token is listed on a DEX, paired with $AIN, and the treasury buys $Token with the project's profits and distributes $Token to the NFT holders. This way, the success of the AIN ecosystem is coupled with the success of each AINFT project as well.

![](/files/dryvd9gcxO23aMiZGmtN)

## Applications

### MiniEggs and $FANCO ([link](https://docs.ainetwork.ai/ainfts/ainft-projects#minieggs-tiniverse-afan))

{% embed url="<https://opensea.io/collection/mysterious-minieggs>" %}

[The Mysterious MiniEggs!](https://miniegg.afan.ai/) is a collection of 100 mysteriously adorable MiniEggs. It is also a live implementation of the AI Network's token economy model. In the MiniEgg ecosystem, there are [$FANCO](https://etherscan.io/token/0x2f85d45985b92087db8cdbc498609a78c58a967c) ERC20 tokens and MiniEgg NFTs. Its major metaverse platforms include aFan (available on [Android](https://play.google.com/store/apps/details?id=com.comcomai.afan), [iOS](https://apps.apple.com/app/afan/id1434385630), and on the [web](https://afan.ai/)), [Tiniverse](https://tiniverse.afan.ai/), and its [Discord](https://discord.gg/dZBg6xA6GC) server. Initially, the profits are shared among the MiniEgg holders equally, but the team is also planning to activate the leveling mechanics, which will reward the holders proportionally to their contributions and activities on the metaverses.

#### Reward-generating activities <a href="#reward-generating-activities" id="reward-generating-activities"></a>

* Playing with MiniEggs on the [MiniEgg+](https://docs.ainetwork.ai/ainfts/ainft-projects/minieggs#miniegg+-guides) devices
* Posting on aFan
* Leaving comments on the posts on aFan
* Liking others' posts on aFan
* Following others on aFan

And many more types of activities will be added to the list!

#### Supply

* MiniEgg NFT
  * Total supply: 100
  * Minting price: 0.1 ETH
* $FANCO ERC20
  * Total supply: 100,000,000,000
  * $FANCO has been released through a fair launch. All profits, i.e. from MiniEggs sales, go to the treasury and will be distributed back to the MiniEgg holders. The rule is simple; MiniEgg holders will earn passive income, as a reward for being the community members and investors, and they can earn even more if they generate activities on certain platforms such as aFan, MiniEgg Discord server, and Tiniverse.

### Soul Fiction ([link](https://docs.ainetwork.ai/ainfts/ainft-projects#soul-fiction))

{% embed url="<https://opensea.io/collection/soulfiction>" %}

Soul Fiction is the largest AINFT project in the world created in part by 15,000 Soulink holders (a.k.a. Soulinkers) and renowned hyper-realism artist, Mr. Kang Hyung Koo. Soulinkers take part in "awakening," or training, the Imperator of Mars, an AI chatbot currently living in the Soul Fiction Discord server but will soon reach Mars. Soulinkers can earn $SOULWATT while training the AI or collectively writing a fiction.

#### Reward-generating activities (WIP)

* Talking to the Imperator of Mars
* Visiting the Soul Gate and interacting with the Imperator of Mars
* Participating in the writing of the Soul Fiction Comic

#### Supply

* Soulink NFT
  * Total supply: 15,000
  * Minting price: 0.08 ETH
* $SOULWATT ERC20
  * Total supply: TBD

### NFT Classics Society ([link](https://docs.ainetwork.ai/ainfts/ainft-projects#nft-classics-society))

*The minting event and OpenSea page are coming soon!*

The NFT Classics Society is showcasing the Original Stradivarius NFT that represents the one and only [Antonio Stradivari, Cremona, 1683, “Cobbett”](https://tarisio.com/cozio-archive/property/?ID=40650) violin. With the help of the members of the NFT Classics Society, the AIs for 3D modeling the violin and converting sounds to those of the violin will be developed and improved. The NFT Classics Society plans to do the same for other amazing classical instruments and the NFT holders will not only get to own one-of-a-kind digital instruments but also earn rewards along the way.

#### Reward-generating activities (WIP)

* TBD

#### Supply

* The Original Stradivarius NFT
  * Total supply: 1
* The Stradivarius AINFT
  * Total supply: TBD
* $TOKEN ERC20
  * Total supply: TBD


# AINFT

<figure><img src="/files/eNNNmeA43twvRgpnNBz3" alt=""><figcaption><p>Figure 1. Structure of an NFT.</p></figcaption></figure>

NFT (non-fungible token) is a digital ID system for assets. An NFT is represented as { contract address, token ID, ownership, metadata }. The metadata such as the token’s name, description, and image URI is usually stored in decentralized storage like IPFS, and the metadata’s storage address (e.g. token URI) along with the token ID and the ownership information is stored in a smart contract. Classical NFTs have static metadata, which means the metadata doesn’t change since its minting time.

<figure><img src="/files/jdrI0gLpzJuSs0vRoGtS" alt=""><figcaption><p>Figure 2. Structure of an AINFT.</p></figcaption></figure>

AINFT is an extension of NFT that has some additional logic attached to it. Often the logic is represented by some extra metadata including AI model specification. The metadata however doesn’t always have to be about artificial intelligence and it can be just some historical data about the NFT, e.g., interaction history between the NFT and users. This data is often dynamic as it can be updated as the AINFT or its community grows.

To make AINFT’s metadata meaningful, it needs to be managed in “trustable” manners, i.e., the update rules of the metadata, which is a core part of tokenomics, need to be applied securely and transparently with the consensus of the community. This can be achieved by storing the metadata in a blockchain database and having the data updates done publicly in the community. AINFT’s typical metadata includes:&#x20;

* specification — Specification of the token’s logic, e.g., AI model type, model parameters, etc&#x20;
* history — Epical data of the token, e.g., event history, reward history, user interaction history, etc&#x20;
* properties — Properties of the token, e.g. token type, token levels, credit balance, achievements, etc

The blockchain database for AINFT’s metadata needs to support dynamic state management including state read/write and permission control. [AIN Blockchain](https://medium.com/ai-network/bottt-ep-1-ain-blockchain-quick-intro-f0810c146e96) is a blockchain designed for such dynamic state management, and [AINFT Factory](https://docs.ainetwork.ai/ainfts/ainft-factory), which is a platform for building community tools for doing that, is adopting AIN Blockchain as a backend.

Persona NFT, which users can chat with, is an example of AINFT. The model information is stored as specification metadata, and the conversation history is stored as history metadata. The history data can be used as back-data for upgrading the token’s properties by the tokenomics.


# AINFT Factory

<figure><img src="/files/mlVi6fkM1EGnEJSrsqeQ" alt=""><figcaption><p>Figure 1. AINFT Factory.</p></figcaption></figure>

AINFT Factory is a tool for [AINFT](https://docs.ainetwork.ai/ainfts/ainft) communities to manage their projects. It helps manage the data of the community members and the AINFTs in trustable manners by bridging the communities and the common backends such as decentralized storage, blockchain database, and AI model backends. More specifically, AINFT Factory is a platform that provides common APIs for AINFT communities to build up their tokenomics. Table 1 summarizes such APIs.

*Table 1. APIs of AINFT Factory.*

<table><thead><tr><th width="122">Category</th><th width="483">API summary</th><th width="97">Notes</th></tr></thead><tbody><tr><td>project</td><td>create project, delete project</td><td></td></tr><tr><td>auth</td><td>manage the access to the project</td><td></td></tr><tr><td>asset</td><td>manage user assets such as NFTs and credits</td><td></td></tr><tr><td>event</td><td>manage community events and rewards</td><td></td></tr><tr><td>store</td><td>manage community item stores</td><td></td></tr><tr><td>AI model</td><td>manage communication between AI models</td><td></td></tr><tr><td>device</td><td>manage devices and games</td><td></td></tr></tbody></table>

<figure><img src="/files/kvfOUAnRhe92OxRHHUUO" alt=""><figcaption><p>Figure 2. Structure of AINFT Factory.</p></figcaption></figure>

Using the APIs provided by AINFT Factory, each community can realize their own tokenomics by building their community bots, community homepages, or community devices. Currently, AINFT Factory APIs support Ethereum [ERC721 tokens](https://eips.ethereum.org/EIPS/eip-721) and [AIN Blockchain](https://medium.com/ai-network/bottt-ep-1-ain-blockchain-quick-intro-f0810c146e96) as a blockchain database. Also the platform provides some Solidity template code for deploying new ERC721 NFTs and TypeScript template code for developing Discord community bots and AI model bots.

The AINFT projects implemented upon AINFT Factory can benefit in:

* Managing user-owned NFT collection lists&#x20;
* Managing metadata in AIN Blockchain&#x20;
* Managing metadata in decentralized storage
* Managing the AI models attached to AINFTs&#x20;
* Managing AINFT devices


# AINFT Projects


# MiniEggs

MiniEggs are unique NFTs, from which AI-powered characters hatch. Every moment you spend with your MiniEgg in the metaverse becomes the data that fuels its growth and shapes its personality and appearances over time. You can also get additional benefits depending on your MiniEgg’s activity levels. AI Network will record data on various NFT activities in the metaverse and use it for creating and improving AI characters.

* **Visit the main page to learn more**: <https://miniegg.afan.ai/>&#x20;
* **Join the aFan Tiniverse Discord Server!**: <https://discord.com/invite/e767UendFs>

## Q\&A

<details>

<summary>What are <a href="https://miniegg.afan.ai">MiniEggs</a>?</summary>

MiniEggs are unique NFTs, from which AI-powered characters hatch. Every moment you spend with your MiniEgg in the metaverse becomes the data that fuels its growth and shapes its personality and appearances over time.

</details>

<details>

<summary>Where can I buy MiniEggs?</summary>

You can buy MiniEggs on [OpenSea](https://opensea.io/collection/mysterious-minieggs).

</details>

<details>

<summary>How can I check my MiniEgg's level and activity history?</summary>

Go to the aFan Tiniverse discord server and use this command in the #minieggs channel: `/stats <ainft_name> <ainft_id>`. The AINFT name will have only the MiniEggs option for now and enter your miniegg number (1, 2, ... 100) for the AINFT ID. The spec is the activity history of your MiniEggs recorded on AIN Blockchain. You will be able to see the numbers increase as you play with your MiniEgg.

In the future, you will be able to check the level & history on [aFan](https://afan.ai/) after connecting your Ethereum address.

</details>

<details>

<summary>How do I increase my MiniEgg's level?</summary>

By playing with it on MiniEgg+. See [How do I play MiniEgg+?](#miniegg+-guides) for more information.

Once it's connected with your aFan account, your aFan activities will also increase its level. The connecting feature is coming soon!

</details>

<details>

<summary>What is MiniEgg+?</summary>

A device through which you can interact with your MiniEggs. The activities on MiniEgg+ are recorded on AIN Blockchain and used to level up your MiniEggs, boost your rewards, and update the personalities of your MiniEggs/AINFTs to be hatched from the MiniEggs.

</details>

<details>

<summary>How can I use MiniEgg+?</summary>

Please refer to the [guide](#miniegg+-guides) below. If you have any questions, visit our [Discord](https://discord.com/invite/e767UendFs) and ask the mods & the community!

</details>

<details>

<summary>Why should I have Miniegg? What's the benefit of being an MiniEgg holder?</summary>

MiniEggs are interactable AINFTs that you can play with. On top of that, the holders will be rewarded with $FANCO for being the sponsors, generating data, and being active in the community.

</details>

<details>

<summary>What is <a href="https://tiniverse.afan.ai/">Tiniverse</a>?</summary>

Tiniverse is a metaverse where AINFTs and humans can explore. There will be AINFT galleries and games in Tiniverse.

</details>

<details>

<summary>What is <a href="https://afan.ai/">aFan</a>?</summary>

aFan is an SNS powered by $FANCO tokens. Activities and users on aFan can be rewarded for or funded with $FANCO. MiniEgg holder benefits will be given to the holder's aFan account.

To get the aFan app:

* [iOS](https://apps.apple.com/app/afan/id1434385630)
* [Android](https://play.google.com/store/apps/details?id=com.comcomai.afan)

</details>

<details>

<summary>What is $FANCO?</summary>

$FANCO is an ERC20 token that fuels the MiniEggs, Tiniverse, and aFan ecosystem. It's used to fund creators and reward users for their activities on metaverse.

</details>

<details>

<summary>Where can I buy $FANCO?</summary>

You can earn $FANCO in aFan by signing up, posting photos, etc. MiniEgg rewards will be given out in $FANCO as well. We're also planning to list $FANCO on Uniswap in the near future.

</details>

## MiniEgg+ Guides

<details>

<summary>Playing MiniEgg+</summary>

Your MiniEgg+ will have either a demo egg or a MiniEgg you bought. We will provide an interface to switch the MiniEggs in the future.

#### Button instructions

* There's an on/off toggle on the left side of the MiniEgg+, and 3 main buttons at the front.
* Left button (L)
  * It opens up the menu on the starting screen and is used to navigate the menu.
* Center button (C)
  * Use this button to select screens and options.
* Right button (R)
  * Use this button to cancel or go back.

#### Currently, you can do these activities with your MiniEgg:

1. Give hearts to your MiniEgg
   1. Press L to see the menu, and C to select the heart:heart: emoji. If you went passed the heart, no worries! keep pressing L until you come back to the heart.
   2. On the heart screen, you'll see the number of hearts available and the time left until the next refill. Give your MiniEgg some love:two\_hearts: by pressing C.
   3. If you run out of hearts, you'll need to wait until the next refill, shown at the top of the screen.
   4. If you want to go back to the initial screen, press R.
2. Play lullabies to your MiniEgg
   1. Press L to see the menu, and select the sleepy face:sleeping: emoji.
   2. You can select which dream your MiniEgg will have. Each dream has different background and music and provides different types of experiences to your MiniEgg. The types of XPs you earn may influence the characteristics of your MiniEgg and/or an AI that hatches from the MiniEgg in the future:wink:
   3. Your MiniEgg will wake from the sweet dream after 3 hours. You can check out how many XPs the egg has gained from the dream. This is the sum of the different types of points you earned, and you can see the detailed breakdown on the AIN Blockchain explorer: <https://insight.ainetwork.ai/database/values/apps/miniegg_plus>/\<your egg id>

</details>

<details>

<summary>Connecting to Wi-Fi</summary>

If you're not connected to Wi-Fi, you'll see a Wi-Fi setting screen when you turn your MiniEgg+ on ("Wi-Fi connection failed. Searching other Wi-Fi...").

Choose one from the options and enter the password (*this may be a little tedious, sorry guys*:crying\_cat\_face:)

If you're already connected to Wi-Fi and would like to change it, you can reset it using a script.

</details>

<details>

<summary>Charging batteries</summary>

You can charge your MiniEgg+ by connecting it to a power source with a cable given along with the device.

</details>

<details>

<summary>Inserting another MiniEgg / NFT</summary>

If you buy a MiniEgg, we will insert your MiniEgg into a MiniEgg+ device. We will soon publish a guide so you can buy another MiniEgg and put it in yourself.

For those who want to insert other NFTs (e.g. BAYC) into MiniEgg+ devices, contact <info@ainetwork.ai>.

</details>

<details>

<summary>Adding a new game</summary>

New games are on their way! We will provide scripts for downloading them to your device and/or a website where you can more easily connect your device and download games.

</details>

<details>

<summary>Troubleshooting</summary>

#### My MiniEgg+ is stuck in the loading screen :scream:

Please try turning it off and on again with the on/off toggle on the left side of the device. If the problem persists, contact our mods at the [Discord #minieggs channel](https://discord.com/invite/e767UendFs).

</details>

If you still have any unanswered questions, ask our mods & community at [Discord](https://discord.com/invite/e767UendFs)!


# Baby Shark

Introducing Baby Shark: Collection No. 2, a limited series of 2,000 unique generative NFTs, each representing a beloved member from the Shark family: Baby Shark, Mommy Shark, Daddy Shark, Grandma Shark, or Grandpa Shark. Each NFT is endowed with special & attractive traits and attributes. Owners can engage in games on the official website or personalize their NFTs using our crafting feature on Baby Shark NFT discord. All data from in-game and crafting activities are recorded on the AI Network, ensuring seamless synchronization of owner-NFT interactions within the metaverse in the future.

* **Visit the main page to learn more**: <https://nft.babyshark.com/>
* **Join the Babk Shark NFT Discord Server!**: <https://discord.com/invite/babyshark>


# Soul Fiction

Soul Fiction is the world’s largest AINFT project, created in part by 15,000 Soulinkers and the renowned hyperrealism artist Mr. Kang, best known for the portrait "The Imperator of Mars," which was later digitized. Soul Fiction is a concoction of AI + NFT + Art featuring the works of Mr. Kang. Soulinkers (owners of the Soulink NFTs) are the artists who create the ultimate masterpiece of Soul Fiction, "The Imperator of Mars" AINFT, by collectively training and augmenting the original chatbot. AI Network enables the community to record all the interactions between the AINFT and Soulinkers and increase the intelligence of the AINFT by large-scale machine learning with the interaction data. AI Network will run the AINFT as a live service on the metaverse.

* **Visit the main page to learn more**: <https://soulfiction.xyz/>
* **Join the Soul Fiction Discord Server!**: <https://discord.com/invite/EhFyRUxKcT>


# NFT Classics Society

Discover the world’s 1st Stradivarius violin AINFT. This exclusive collection brings the classical masterpiece into the metaverse. The collection includes 3D images of the instrument and AI models that recreate the original sound. It is the 1st collection presented by the NFT Classics Society, a DAO for people passionate about classical music and bringing its capacity to evoke emotions to the metaverse. AI Network allows AI developers to implement 3D models or AI compositions in the metaverse freely, transform them into AINFTs, and play AI-empowered musical instruments.

* **Visit the main page to learn more**: <https://www.nftclassicsociety.ai/>
* **Join the NFT Classics Society Discord Server!**: <https://discord.com/invite/JgqXcpHXAv>


# Developer Reference

There are reference for developers to develop something with AINFT.


# Ainft-Js

Ainft-Js is typescript SDK for interacting with AINFT and AINFT Factory.

Github: <https://github.com/ainft-team/ainft-js>

Docs: [https://ainft-team.github.io/ainft-js](https://ainft-team.github.io/ainft-js/)


# AINFT tutorial

In this tutorial, you will learn how to mint and manage AINFT with ainft-js.


# Create AINFT object and Mint

You can create AINFT compliant 721 standard on AIN Blockchain. In this tutorial, We create AINFT on testnet and mint it.

### Requirement

* Node
* IDE (recommend VS Code)

### Step1. Initialize project

First, Create project to create AINFT. Make your directory and move it.

```bash
mkdir my-ainft
cd my-ainft
```

and Initialize project.

```bash
npm init
```

### Step2. Install ainft-js

Install ainft-js. We can create, mint and transfer AINFT with ainft-js.

```bash
npm install @ainft-team/ainft-js
```

### Step3. Create Account

Create account to create AINFT. If you have ain account, you can use it.

```typescript
const AinftJs = require('@ainft-team/ainft-js').default;

const account = AinftJs.createAccount();
console.log(account);

// {
//   address: '0x74703a44905daB6582d62A45705a1c3ff966523f',
//   private_key: ... ,
//   public_key: '9451c9c91f84ef5cc5f83fe86413c9eb283a6ba3924d0a351ac598c3895b9f6a57b10513a885a98aff8ccea2aa3101c07f799bcb25cbcb1184f67f6c2cb72541'
// }
```

If you have AIN Wallet, you can use account in Wallet.

Like below picture, you can export private key of account you want in wallet account setting.

<figure><img src="/files/ElrfVhPDzDFYX4bHIt9e" alt="" width="300"><figcaption><p>Export private key from ain wallet account</p></figcaption></figure>

### Step4. Get testnet ain from faucet

In order to create NFT, we need some ain. In Faucet, you can get some ain for tutorial. Enter your ain account address and get some ain.

> <https://faucet.ainetwork.ai/>

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

After then, you can check your balance in Wallet.

<figure><img src="/files/VXAFwoPvP5OpODNSaMYE" alt="" width="360"><figcaption></figcaption></figure>

You can also check insight by entering the address in the search box at the top right.

> <https://testnet-insight.ainetwork.ai>

<figure><img src="/files/43VGJwfEGRDEpS3zk1KS" alt=""><figcaption></figcaption></figure>

### Step5. Create Ainft object

Then, we’ll intialize ainft-js and create AINFT object. Use create function with NFT’s name and symbol you want. You can look appId, nftId and txHash as resulting in standard out. and You can check if transaction is completed by enter txHash in insight. Please check it and proceed to the next step.

{% code fullWidth="false" %}

```typescript
const config = {
  ainftServerEndpoint: 'https://ainft-api-dev.ainetwork.ai',
  ainBlockchainEndpoint: 'https://testnet-api.ainetwork.ai',
}
const ainftJs = new AinftJs('YOUR_PRIVATE_KEY', config);

const name = 'ainft_for_tutorial';
const symbol = 'TUTORIAL';

ainftJs.nft.create(name, symbol)
.then((res) => {
	const { txHash, ainftObject } = res;
	console.log(txHash);
	console.log(ainftObject.id);
	console.log(ainftObject.appId);
})
.catch((error) => {
	console.log(error);
});

// 0xe3c4c0e4982a7ebc1224d9e8ff84a86d17ff4facd5ac25e6bec2c9bfb32da8c2
// 0x799a71A8DDdECC23F1B15d222BcB01ae674751B8
// ainft721_0x799a71a8dddecc23f1b15d222bcb01ae674751b8
```

{% endcode %}

You can check the transaction results by entering the transaction hash in the search box at the top right.

> <https://testnet-insight.ainetwork.ai/>

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

### Step6. Mint

Finally, Let’s mint AINFT. You can mint AINFT with tokenId you want to mint and the ain account address you want to receive AINFT.

You can see if transaction is complete by retrieving tx hash in insight.

```typescript
const to = '0x74703a44905daB6582d62A45705a1c3ff966523f'; // Replace to your receiver address.
const tokenId = '1'; // Replace to token Id you want.
const ainftObjectId = '0x799a71A8DDdECC23F1B15d222BcB01ae674751B8'; // Replace to your ainft object id.

const main = async () => {
  try {
    const ainftObject = await ainftJs.nft.get(ainftObjectId);
    const result = await ainftObject.mint(to, tokenId);
    console.log(result);
  } catch(error) {
    console.log(error);
  }
}

main();

// {
//   tx_hash: '0xbdca2430d425e78114a921eda073400cdf8ad9d4c05e8fda59931b39a69455f8',
//     result: {
//     gas_amount_total: { bandwidth: [Object], state: [Object] },
//     gas_cost_total: 0,
//       result_list: { '0': [Object], '1': [Object], '2': [Object], '3': [Object] },
//     gas_amount_charged: 0
//   }
// }
```

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

You can check minted AINFT in insight database!

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

Find out how to transfer AINFT issued in the next chapter!


# Transfer AINFT

This tutorial describes how to transfer AINFT to other account with ainft-js. If you don’t have AINFT, See AINFT tutorial - Create & Mint.

### Transfer

You need an account that owns AINFT, nftId, tokenId and an address to receive.

```typescript
const AinftJs = require('@ainft-team/ainft-js').default;

const privateKey = 'TOKEN_OWNER_PRIVATE_KEY';
const config = {
  ainftServerEndpoint: 'https://ainft-api-dev.ainetwork.ai',
  ainBlockchainEndpoint: 'https://testnet-api.ainetwork.ai',
}
const ainftJs = new AinftJs(privateKey, config);
```

Then send the AINFT.

```jsx

const ainftObjectId = '0x6c4605D7a3abAd19f9BbA986746aDF9fFCBE6f9A'; // Replace to your ainft object Id.
const from = '0xB1bFB4f0E77d8e427f27653E73c464AccF6dcEE3'; // Replace to token owner address.
const to = '0x583E38d525283233293f405862550Fc910650893'; // Replace to receiver address.
const tokenId = '1'; // Replace your token Id.

const main = async () => {
	try {
		const ainftObject = await ainftJs.nft.get(ainftObjectId);
		const result = await ainftObject.transfer(from, to, tokenId);
		console.log(result);
	} catch(error) {
		console.log(error);
	}
}

main();

// {
//   tx_hash: '0x439bde3f9526119d037411eb0b4a27c22196ce4df93b982f2d627d47e3ed8a57',
//     result: {
//     gas_amount_total: { bandwidth: [Object], state: [Object] },
//     gas_cost_total: 0,
//       func_results: {
//       '0x6c4605D7a3abAd19f9BbA986746aDF9fFCBE6f9A_trigger_transfer': [Object]
//     },
//     code: 0,
//       bandwidth_gas_amount: 1,
//         gas_amount_charged: 0
//   }
// }
```

You can check if transaction is completed using `tx_hash` in insight.

> <https://testnet-insight.ainetwork.ai/>

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

and In insight database, you can see updated owner information.

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


# Set metadata of AINFT

This tutorial describes how to update AINFT’s metadata with ainft-js. If you don’t have AINFT, See AINFT tutorial - Create & Mint.

### Set metadata

Only AINFT object owner can update metadata of each token. Metadata is configured as JSON format.

```jsx
const AinftJs = require('@ainft-team/ainft-js').default;

const privateKey = 'AINFT_OBJECT_OWNER_PRIVATE_KEY';
const config = {
  ainftServerEndpoint: '<https://ainft-api-dev.ainetwork.ai>',
  ainBlockchainEndpoint: '<https://testnet-api.ainetwork.ai>',
}
const ainftJs = new AinftJs(privateKey, config);

const ainftObjectId = '0x6c4605D7a3abAd19f9BbA986746aDF9fFCBE6f9A';
const tokenId = '1';
const metadata = {
	name: 'my first token',
	image: '<https://miro.medium.com/v2/resize:fit:2400/1*GWMy0ibykACFKS_rRxFlcw.png>'
}

const main = async () => {
	try {
		const ainftObject = await ainftJs.nft.get(ainftObjectId);
	  const ainft = await ainftObject.getToken(tokenId);
	  const result = await ainft.setMetadata(metadata);
	  console.log(result);
	} catch(error) {
		console.log(error);
	}
}

main();

// {
//   tx_hash: '0x9009753dcb212a0b4c898022e38afd8d5a02200ef6429a4e4048ddf9c0e6a5a1',
//     result: {
//     gas_amount_total: { bandwidth: [Object], state: [Object] },
//     gas_cost_total: 0,
//       func_results: {
//       '0x6c4605D7a3abAd19f9BbA986746aDF9fFCBE6f9A_trigger_metadata': [Object]
//     },
//     code: 0,
//       bandwidth_gas_amount: 1,
//         gas_amount_charged: 0
//   }
// }
```

You can check if transaction is completed using `tx_hash` in insight.

> <https://testnet-insight.ainetwork.ai/>

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

You can check updated metadata through the insight database.

<figure><img src="/files/0lXGU0DCzsGn6HZ5Wxrr" alt=""><figcaption></figcaption></figure>


# Search and Retrieve AINFT

This tutorial describe how to retrieve AINFTs by id, name, symbol and userAddress.

### Retrieve AINFTs

You can retrieve AINFTs using `geAinftsByAccount` or `getAinftsByAinftObject` .

```jsx
ainftJs.nft.getAinftsByAccount(userAddress)
	.then((res) => {
		console.log(JSON.stringify(res, null, 2));
	})
	.catch((error) => {
		console.log(error);
	})
```

```jsx
ainftJs.nft.getAinftsByAinftObject(ainftObjectId)
	.then((res) => {
		console.log(JSON.stringify(res, null, 2));
	})
	.catch((error) => {
		console.log(error);
	})
```

### Search Ainft object and AINFTs

Also, you can search ainft objects or AINFTs. Search options are below.

* ainftObjectId - The ID of Ainft object
* name - The name of Ainft object
* symbol - The symbol of Ainft object
* tokenId - Token ID of AINFT
* userAddress - Address of AINFT owner

```jsx
ainftJs.nft.searchAinftObjects({ ainftObjectId })
	.then((res) => {
		console.log(JSON.stringify(res, null, 2));
	})
	.catch((error) => {
		console.log(error);
	});
```

```jsx
ainftJs.nft.searchNfts({ ainftObjectId })
	.then((res) => {
		console.log(JSON.stringify(res, null, 2));
	})
	.catch((error) => {
		console.log(error);
	});
```

#### Response

```jsx
// Return Type
{
	nfts: Array<{
		owner: string,
		tokenId: string,
		tokenURI: string,
		ainftObject: {
			id: string,
			name: string,
			symbol: string,
			owner: string,
		}
		metadata: object,
	}>,
	isFinal: boolean,
	cursor: string,
}

{
	ainftObjects: Array<{
		id: string,
		name: string,
		symbol: string,
		owner: string,
	}>,
	isFinal: boolean,
	cursor: string,
}
```

### Limit

Search function retrieves 20 items by default. If you want to set number of result items, you can use limit option. Maximum limit value is 100.

```jsx
const ainftObjects = await ainftJs.nft.searchAinftObjects({ limit: 5 })
```

then, you can retrieve more with using cursor.

```jsx
const nextAinftObjects = await ainftJs.nft.searchAinftObjects({ limit: 5, cursor: '0x460e3BC2E6D98Bc2b434DE4854Bf4a08E63eb3A2' });
```

The cursor value is included in result of search. If you search nfts, usage is the same.


# What is AIN Wallet?

AI Network Wallet, or simply “AIN Wallet”, is a chrome extension that allows you to manage accounts and assets on AI Network. You can download it from [here](https://chrome.google.com/webstore/detail/ain-wallet/hbdheoebpgogdkagfojahleegjfkhkpl?hl=ko).


# AIN Wallet API

This document describes how to access AIN Wallet in a JavaScript based web app. Before following this article, make sure you have installed the AIN Wallet.

## What does AIN Wallet API do?

AIN Wallet injects a JavaScript API into websites using the `window.ainetwork` object. This API allows websites to request users' AI Network accounts, and assists users in signing messages or sending transactions.

## APIs

#### window\.ainetwork.getAddress()

```typescript
window.ainetwork.getAddress(): Promise<string>
```

Returns the address of the currently active account.

#### window\.ainetwork.getAccount()

<pre class="language-typescript"><code class="lang-typescript"><strong>interface Account {
</strong><strong>  name: string
</strong><strong>  address: string
</strong><strong>}
</strong><strong>
</strong><strong>window.ainetwork.getAccount(): Promise&#x3C;Account>
</strong></code></pre>

Returns the address of the currently active account.

#### window\.ainetwork.getNetwork()

<pre class="language-typescript"><code class="lang-typescript"><strong>interface Network {
</strong><strong>  chainId: number
</strong><strong>  name: string
</strong><strong>}
</strong><strong>
</strong><strong>window.ainetwork.getAccount(): Promise&#x3C;Network>
</strong></code></pre>

Returns the address of the currently active account.

#### window\.ainetwork.getBalance()

```typescript
window.ainetwork.getBalance(): Promise<number>
```

Returns the AIN token balance of the currently active account.

#### window\.ainetwork.signMessage()

```typescript
window.ainetwork.signMessage(message: string): Promise<string>
```

Returns the signature for `message` signed with the private key of the currently active account.

#### window\.ainetwork.sendTransaction()

```typescript
interface SetOperation {
  type: "SET_VALUE" | "INC_VALUE" | "DEC_VALUE" | "SET_RULE" | "SET_OWNER" | "SET_FUNCTION";
  ref: string;
  value: any | undefined | null;
  is_global?: boolean;
}

interface SetMultiOperation {
  type: "SET";
  op_list: SetOperation[];
}

interface TransactionInput {
  parent_tx_hash?: string;
  operation: SetOperation | SetMultiOperation;
  nonce?: number;
  address?: string;
  timestamp?: number;
  gas_price?: number;
  billing?: string;
}

window.ainetwork.sendTransaction(txInput: TransactionInput): Promise<string>
```

Sends transaction to the AI Network, and returns the transaction hash.


# AIN Improvement Memos (AIMs)

https\://github.com/ainblockchain/ainetwork-docs/tree/master/AIM\_docs

| ID      | Title                                                 | Link                                                                                                                                            | Status   |
| ------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| AIM-001 | Changeable Validator Set                              | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIM_docs/AIM-001_Changeable_Validator_Set-20210513.pdf)                            | Accepted |
| AIM-002 | Better Randomness and Proposer Selection              | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIM_docs/AIM-002_Better_Randomness_and_Proposer_Selection-20210513.pdf)            | Accepted |
| AIM-003 | Genesis Parameter Files                               | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIM_docs/AIM-003_Genesis_Parameter_Files-20210513.pdf)                             | Accepted |
| AIM-004 | Explicit Write Permissions of Native Functions        | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIM_docs/AIM-004_Explicit_Write_Permissions_of_Native_Functions-20210513.pdf)      | Accepted |
| AIM-005 | Block Storage Optimization                            | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIM_docs/AIM-005_Block_storage_optimization-20210513.pdf)                          | Accepted |
| AIM-006 | Including Nonce Tracker In The State                  | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIM_docs/AIM-006_Including_nonce_tracker_in_the_state-20210513.pdf)                | Accepted |
| AIM-007 | State vs. Status                                      | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIM_docs/AIM-007_State_vs_Status-20210513.pdf)                                     | Accepted |
| AIM-008 | Chained Native Function Calls and Write Permissions   | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIM_docs/AIM-008_Chained_native_function_calls_and_write_permissions-20210513.pdf) | Accepted |
| AIM-009 | Integrating manage\_app With App Owner / Rule Configs | TBA                                                                                                                                             | WIP      |
| AIM-010 | Function Results in Tx Results                        | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIM_docs/AIM-010_Function_Results_in_Tx_Results-20210513.pdf)                      | Accepted |


# AIN Improvement Proposals (AIPs)

https\://github.com/ainblockchain/ainetwork-docs/tree/master/AIP\_docs

| ID      | Title                                            | Summary                                                                                                                                     | Link                                                                                                                                           | Status                                                                               |
| ------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| AIP-001 | Numbered, Ordered, and Unordered Nonces          | In addition to the numbered nonce (Ethereum-style), introduce two more nonce types: ordered and unordered                                   | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-001_Numbered_ordered_and_unordered_nonces-20210512.pdf)              | Accepted (see [Nonce section](/ain-blockchain/ai-network-design/transactions/nonce)) |
| AIP-002 | Micropayment Protocol for Low-Level Services     | Support micropayments between human-to-machine or machine-to-machine for low latency and reasonable transaction fee                         | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-002_Micropayment_Protocol_for_Low-Level_Services-20210512.pdf)       | In Review                                                                            |
| AIP-003 | Blockchain Charging Policy                       | How to charge blockchain maintenance costs                                                                                                  | -                                                                                                                                              | **Deprecated (See AIP-015 & 016 instead)**                                           |
| AIP-004 | Blockchain Apps Meta-data                        | Allow apps meta-data to be added to the blockchain and integrated with Insight (or other blockchain viewers) for search engine optimization | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-004_Blockchain_apps_meta-data-20210512.pdf)                          | Accepted                                                                             |
| AIP-005 | Token Staking Service                            | Provide a service for token staking                                                                                                         | -                                                                                                                                              | **Deprecated (See AIP-19 instead)**                                                  |
| AIP-006 | State Version Control                            | Introduce an efficient state version control for block versions of Streamlet Consensus algorithm                                            | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-006_State_Version_Control-20210512.pdf)                              | Accepted                                                                             |
| AIP-007 | Provable Blockchain States                       | Provide proof of blockchain states                                                                                                          | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-007_Provable_Blockchain_States-20210512.pdf)                         | Accepted                                                                             |
| AIP-008 | Sharding                                         | Define minimal requirements for a scalable blockchain and provide a design proposal                                                         | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-008_Sharding-20210512.pdf)                                           | Accepted                                                                             |
| AIP-009 | Cross-Shard Token Swap                           | Provide a design of cross-shard transactions for a narrow scenario: Cross-shard token swap transactions (check-in and check-out)            | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-009_Cross-Shard_Token_Swap-20210512.pdf)                             | Accepted                                                                             |
| AIP-010 | Simple Payment Service                           | Provide a service for payments                                                                                                              | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-010_Simple_Payment_Service-20210512.pdf)                             | Accepted                                                                             |
| AIP-011 | Service Account & Transfer                       | Provide new features for 1) service accounts (like business bank account) and 2) money transfer from/to them                                | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-011_Service_Account_and_Transfer-20210512.pdf)                       | Accepted                                                                             |
| AIP-012 | Escrow Service                                   | Provide a design of escrow service to reserve tokens for multilateral transactions in other services (e.g. payment)                         | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-012_Escrow_Service-20210512.pdf)                                     | Accepted                                                                             |
| AIP-013 | P2P Protocol Version Handling                    | Handle p2p protocol version compatibility so that blockchain nodes can be upgraded minimizing service discontinuation                       | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-013_P2P_Protocol_Version_Handling-20210512.pdf)                      | Accepted                                                                             |
| AIP-014 | Critical Resources of Blockchain Services        | Define, track, and constraint AIN Blockchain’s critical resources available for the blockchain service users                                | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-014_Critical_Resources_of_Blockchain_Services-20210512.pdf)          | Accepted                                                                             |
| AIP-015 | Gas Fee Charging                                 | Introduce Gas Fee charging protocol Version 1 of AIN Blockchain                                                                             | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-015_Gas_Fee_Charging-20210512.pdf)                                   | Accepted                                                                             |
| AIP-016 | Gas Fee Redistribution                           | Introduce Gas Fee redistribution protocol Version 1 of AIN Blockchain                                                                       | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-016_Gas_Fee_Redistribution_Protocol-20210512.pdf)                    | Accepted                                                                             |
| AIP-017 | Billing Accounts                                 | Introduce billing accounts for supporting convenient payment of gas fees                                                                    | TBA                                                                                                                                            | WIP                                                                                  |
| AIP-018 | Consistency & Reusability of Blockchain Services | List up all services available so far and seek improvement ideas for their consistency and reusability                                      | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-018_Consistency_and_reusability_of_blockchain_services-20210512.pdf) | Accepted                                                                             |
| AIP-019 | Staking Service                                  | Provide a design of staking service to be used for validator staking and general-purpose staking within apps                                | [Link](https://github.com/ainblockchain/ain-docs/blob/master/AIP_docs/AIP-019_Staking_Service-20210512.pdf)                                    | Accepted                                                                             |


