> ## Documentation Index
> Fetch the complete documentation index at: https://docs.therootnetwork.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Building with Native API

The most optimal way to interact with the Native API on The Root Network is via `@polkadot/api` package in combination with our package `@therootnetwork/api`. It provides web3 developers the ability to query and interact with The Root Network node using Javascript/Typescript. For installation instructions, see [Install Native API](/build/substrate/api-package).

One of the most important things to understand about the `@polkadot/api` is that most interfaces are actually generated automatically when connected to a running node. This is quite a departure from other APIs in projects with static interfaces. While it may sound intimidating, this concept is actually a powerful feature present in any Substrate chain. It enables the API to be used in environments where the chain is customized.

To unpack this, we will start with the metadata and explain what it actually provides, since it is critical to understand how to interact with the API and any underlying chain.

## Metadata

When the API connects to a node, one of the first things it does is retrieve the metadata and decorate the API based on the metadata information. The metadata effectively provides data in the form of `api.<type>.<module>.<section>` that fits into one of the following categories:

* `consts` - All runtime constants, e.g. `api.consts.balances.existentialDeposit`. These are not functions; rather, accessing the endpoint immediately yields the result as defined.

* `query` - All chain state, e.g. `api.query.system.account(<accountId>)`.

* `tx` - All extrinsics, e.g. `api.tx.balances.transfer(<accountId>, <value>)`.

Additionally, the metadata also provides information on `events`. These are queryable via the `api.query.system.events()` interface and also appear on transactions. Both these cases are detailed later.

None of the information contained within the `api.{consts, query, tx}.<module>.<method>` endpoints are hardcoded in the API. Rather, everything is fully decorated by what the metadata exposes and is, therefore, completely dynamic. This means that when you connect to different chains, the metadata and API decoration will change and the API interfaces will reflect what is available on the chain you are connected to.

## Runtime Types

Everything the API returns is a type with a consistent interface: `Codec`. This means that a `Vec<u32>` (an array of `u32` values), as well as a `Struct` (an object) or an `Enum`, has the same consistent base interface. Specific types will have values based on the type - decorated and available.

As a minimum, anything returned by the API, be it a `Vec<...>`, `Option<...>`, `Struct` or any normal type will always have the following methods - as defined on the `Codec` interface:

* `.eq(<other value>)` - checks for equality against the other value. In all cases, it will accept "like" values, i.e. in the case of a number, you can pass a primitive (such as `1`), a hex value (such as `0x01`) or even a `Unit8Array`

* `toHex()` - returns a hex-base representation of the value, always prefixed by `0x`

* `toHuman()` - returns Human-parsable JSON structure with values formatted as per the settings

* `toJSON()` - returns a JSON-like representation of the value. This is generally used when calling `JSON.stringify(...)` on the value

* `toString()` - returns a string representation. In some cases, this performs additional encoding, i.e. for `Address`, `AccountId` and `AccountIndex`, it will encode to the ss58 address

* `.toU8a()` - returns a `Uint8Array` representation of the encoded value (generally exactly as passed to the node, where values are SCALE encoded)

Additionally, the following getters and utilities are available:

* `.isEmpty` - `true` if the value is an all-empty value, i.e. `0` in for numbers, all-zero for Arrays (or anything `Uint8Array`), `false` is non-zero

* `.hash` - a `Hash` (once again with all the methods above) that is a `blake2-256` representation of the contained value

## Chain Defaults

In addition to the `api.[consts | query | tx]` detailed above, the API, upon connecting to a chain, fills in some information and makes it available directly on the API interface. These include -

* `api.genesisHash` - The genesisHash of the connected chain

* `api.runtimeMetadata` - The metadata as retrieved from the chain

* `api.runtimeVersion` - The chain runtime version (including specification/implementation versions and types)

## Chain State

The `api.rpc.<section>.<method>` provides low-level interfaces to read the chain state that's not necessarily bound to the pallet storage. It's also the commonplace to add additional data query for the custom pallets, e.g. `api.rpc.tokenUri`.

```ts
// Initialize the API as in previous sections
...

// Retrieve the chain name
const chain = await api.rpc.system.chain();

// Retrieve the latest header
const lastHeader = await api.rpc.chain.getHeader();

// Log the information
console.log(`${chain}: last block #${lastHeader.number} has hash ${lastHeader.hash}`);
```

It's possible to subscribe to RPC calls and receive up-to-date data. For instance, subscribe to a new block height change.

```ts
...
let count = 0;

// Subscribe to the new headers
const unsubscribe = await api.rpc.chain.subscribeNewHeads((lastHeader) => {
  console.log(`${chain}: last block #${lastHeader.number} has hash ${lastHeader.hash}`);

  if (++count === 10) {
    unsubscribe();
  }
});
```

Since we are dealing with a subscription, we now pass a callback into the `subscribeNewHeads` function, and this will be triggered on each header as they are imported. The same pattern applies to each of the `api.rpc.subscribe` functions. As the last parameter, a callback should be provided to stream the latest data as it becomes available.

In general, whenever we create a subscription, we would like to clean up after ourselves and unsubscribe. Assuming we only want to log the first 10 headers, the above example demonstrates the use of the `unsubscribe()` function.

## Chain Storage

The `api.query.<pallet>.<method>` interfaces are used to read the public storage in each available pallet. Behind the scenes, the API uses the metadata information provided to construct queries based on the location and parameters provided to generate state keys and then queries these via RPC.

```ts
// Initialize the API as in previous sections
...

// The actual address that we will use
const ADDR = '0xE04CC55ebEE1cBCE552f250e85c57B70B2E2625b';

const [now, { nonce, data: balance }] = await Promise.all([
  api.query.timestamp.now(),
  api.query.system.account(ADDR)
]);

console.log(`${now}: balance of ${balance.free} and a nonce of ${nonce}`);
```

Similar to RPC calls, sometimes it's necessary to subscribe to the chain state to handle your application logic. Fortunately, the API provides a straightforward way to do that.

```ts
...

// Retrieve the current timestamp via subscription
const unsubscribe = await api.query.timestamp.now((moment) => {
  console.log(`The last block has a timestamp of ${moment}`);

  // unsubscribe(); call to stop receiving updates
});
```

Instead of the `await` returning the actual one-time value, it returns a subscription `unsubscribe()` function. This function can be used to stop the subscription and clean up any underlying RPC connections. The supplied callback will contain the value streamed from the node as it changes.

## Transaction

Transaction endpoints are exposed, as determined by the metadata, on the `api.tx.<pallet>.<method>` endpoint. These allow you to submit transactions for inclusion in blocks, whether it's transfers, setting information or any other operation your chain supports.

The Root Network supports the ECDSA key-pair standard. To submit a transaction, make sure you have a valid account with a small amount of `XRP` tokens to cover the transaction fee. Create a `keyring` instance as follows:

```ts
import { Keyring } from "@polkadot/keyring";
import { stringToU8a, u8aToHex, hexToU8a } from "@polkadot/util";

// create a keyring with some non-default values specified
const keyring = new Keyring({ type: "ethereum" });
const seedU8a = hexToU8a(ALICE_PRIVATE_KEY);
const alice = keyring.addFromSeed(seedU8a);
```

Once that is done, to transfer a balance from Alice to Bob as per the example above, use the code below:

```ts
...
// Sign and send a transfer from Alice to Bob
const txHash = await api.tx.balances
  .transfer(BOB, 12345)
  .signAndSend(alice);

// Show the hash
console.log(`Submitted with hash ${txHash}`);
```

The result of this call is the transaction hash. This is a hash of the data; receiving it does not mean the transaction has been included. It only means that the hash has been accepted for propagation by the node.

<Warning>
  **Caution**: Transaction hash in Substrate-based blockchain is generally unique within a block but not across the chain. [Check out this article](https://wiki.polkadot.network/docs/build-protocol-info#unique-identifiers-for-extrinsics) for more details.
</Warning>

Similar to `api.rpc` and `api.query` interfaces, it's possible to subscribe to the transaction state change to determine if it's been included in the block or not.

```ts
...
// Make a transfer from Alice to Bob, waiting for inclusion
const unsubscribe = await api.tx.balances
  .transfer(BOB, 12345)
  .signAndSend(alice, (result) => {
    console.log(`Current status is ${result.status.type}`);

    if (result.status.isInBlock) {
      console.log(`Transaction included at blockHash ${result.status.asInBlock}`);
    } else if (result.status.isFinalized) {
      console.log(`Transaction finalized at blockHash ${result.status.asFinalized}`);
      unsubscribe();
    }
  });
```

As per all previous subscriptions, the transaction subscription returns `unsubscribe()` and the actual method has a subscription callback. The `result` object has two parts: `events` (to be covered in the next section) and the `status` enum.

When the `status` enum is in `Finalized` state (checked via `isFinalized`), the underlying value contains the block's hash where the transaction has been finalized. `Finalized` will follow `InBlock`, which is the block where the transaction has been included. `InBlock` does not mean the block is finalized, but rather applies to the transaction state, where `Finalized` means that the transaction cannot be forked off the chain.

## Transaction Events

Any transaction will emit events. As a bare minimum, this will always be either a `system.ExtrinsicSuccess` or `system.ExtrinsicFailed` event for the specific transaction. These provide the overall execution result for the transaction, i.e. execution has succeeded or failed.

Depending on the transaction sent, some other events may be emitted. For instance, for a `balances.transfer` this could include one or more of `Transfer`, `NewAccount` or `ReapedAccount`, as defined in the substrate `balances` event defaults.

To display or act on these events, we can do the following:

```ts
...
// Make a transfer from Alice to BOB, waiting for inclusion
const unsubscribe = await api.tx.balances
  .transfer(BOB, 12345)
  .signAndSend(alice, ({ events = [], status, txHash }) => {
    console.log(`Current status is ${status.type}`);

    if (status.isFinalized) {
      console.log(`Transaction included at blockHash ${status.asFinalized}`);
      console.log(`Transaction hash ${txHash.toHex()}`);

      // Loop through Vec<EventRecord> to display all events
      events.forEach(({ phase, event: { data, method, section } }) => {
        console.log(`\t' ${phase}: ${section}.${method}:: ${data}`);
      });

      unsubscribe();
    }
  });
```

<Warning>
  **Caution**: Be aware that when a transaction status is `isFinalized`, it means it is included, but it may still have failed - for instance, if you try to send a larger amount that you have free, the transaction is included in a block. However, from an end-user perspective, the transaction failed since the transfer did not occur. In these cases, a `system.ExtrinsicFailed` event will be available in the events array.
</Warning>

## Payment Information

The RPC endpoints expose weight/payment information that takes an encoded extrinsic and calculates the on-chain weight fees for it. A wrapper for this is available on the tx itself, taking exactly the same parameters as you would pass to a normal `.signAndSend` operation, specifically `.paymentInfo(sender, <any options>)`. To expand on our previous example:

```ts
// construct a transaction
const transfer = api.tx.balances.transfer(BOB, 12345);

// retrieve the payment info
const { partialFee, weight } = await transfer.paymentInfo(alice);

console.log(`transaction will have a weight of ${weight}, with ${partialFee.toHuman()} weight fees`);

// send the tx
transfer.signAndSend(alice, ({ events = [], status }) => { ... });
```
