Prerequisites

## Prerequisites

Before converting assets on Asset Hub, you must ensure you have:

- Access to the [Polkadot.js Apps](https://polkadot.js.org/apps) interface and a connection with the intended blockchain.
- A funded wallet containing the assets you wish to convert and enough available funds to cover the transaction fees.
- An asset registered on Asset Hub that you want to convert. If you haven't created an asset on Asset Hub yet, refer to the [Register a Local Asset](/chain-interactions/token-operations/register-local-asset/) or [Register a Foreign Asset](/chain-interactions/token-operations/register-foreign-asset/) documentation to create an asset.


Create a Liquidity Pool

## Create a Liquidity Pool

If an asset on Asset Hub does not have an existing liquidity pool, the first step is to create one.

The asset conversion pallet provides the `createPool` extrinsic to create a new liquidity pool, creating an empty liquidity pool and a new `LP token` asset.

!!! tip
    A testing token with the asset ID `1112` and the name `PPM` was created for this example.

As stated in the [Test Environment Setup](#test-environment-setup) section, this tutorial is based on the assumption that you have an instance of Polkadot Asset Hub running locally. Therefore, the demo liquidity pool will be created between DOT and PPM tokens. However, the same steps can be applied to any other asset on Asset Hub.

From the Asset Hub perspective, the Multilocation that identifies the PPM token is the following:

```javascript
{
  parents: 0,
  interior: {
    X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }]
  }
}
```

The `PalletInstance` value of `50` represents the Assets pallet on Asset Hub. The `GeneralIndex` value of `1112` is the PPM asset's asset ID.

To create the liquidity pool, you can follow these steps:

1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface:

    1. Select **Developer** from the top menu.
    2. Click on **Extrinsics** from the dropdown menu.

    ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp)

2. Select extrinsic to create the pool:

    1. Select the **`AssetConversion`** pallet.
    2. Choose the **`createPool`** extrinsic from the list of available extrinsics.

    ![Create Pool Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-02.webp)

3. Fill in the required fields:

    1. **`asset1`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents.

        ```javascript
        {
          parents: 0,
          interior: 'Here'
        }
        ```

    2. **`asset2`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies.

        ```javascript
        {
          parents: 0,
          interior: {
            X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }]
          }
        }
        ```

    3. Click on **Submit Transaction** to create the liquidity pool.

    ![Create Pool Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-03.webp)

Signing and submitting the transaction triggers the creation of the liquidity pool. To verify the new pool's creation, check the **Explorer** section on the Polkadot.js Apps interface and ensure that the **`PoolCreated`** event was emitted.

![Pool Created Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-04.webp)

As the preceding image shows, the **`lpToken`** ID created for this pool is 19. This ID is essential to identify the liquidity pool and associated LP tokens.


Add Liquidity to a Pool

## Add Liquidity to a Pool

The `addLiquidity` extrinsic allows users to provide liquidity to a pool of two assets. Users specify their preferred amounts for both assets and minimum acceptable quantities. The function determines the best asset contribution, which may vary from the amounts desired but won't fall below the specified minimums. Providers receive liquidity tokens representing their pool portion in return for their contribution.

To add liquidity to a pool, follow these steps:

1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface:

    1. Select **Developer** from the top menu.
    2. Click on **Extrinsics** from the dropdown menu.

    ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp)

2. Select extrinsic to add liqudity:

    1. Select the **`assetConversion`** pallet.
    2. Choose the **`addLiquidity`** extrinsic from the list of available extrinsics.

    ![Add Liquidity Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-05.webp)

3. Fill in the required fields:

    1. **`asset1`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents.

        ```javascript
        {
          parents: 0,
          interior: 'Here'
        }
        ```

    2. **`asset2`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies.

        ```javascript
        {
          parents: 0,
          interior: {
            X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }]
          }
        }
        ```

    3. **`amount1Desired`**: The amount of the first asset that will be contributed to the pool.
    4. **`amount2Desired`**: The quantity of the second asset intended for pool contribution.
    5. **`amount1Min`**: The minimum amount of the first asset that will be contributed.
    6. **`amount2Min`**: The lowest acceptable quantity of the second asset for contribution.
    7. **`mintTo`**: The account to which the liquidity tokens will be minted.
    8. Click on **Submit Transaction** to add liquidity to the pool.

    ![Add Liquidity Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-06.webp)

    !!! warning
        Ensure that the appropriate amount of tokens provided has been minted previously and is available in your account before adding liquidity to the pool.

    In this case, the liquidity provided to the pool is between DOT tokens and PPM tokens with the asset ID 1112 on Polkadot Asset Hub. The intention is to provide liquidity for 1 DOT token (`u128` value of 1000000000000 as it has 10 decimals) and 1 PPM token (`u128` value of 1000000000000 as it also has 10 decimals).

Signing and submitting the transaction adds liquidity to the pool. To verify the liquidity addition, check the **Explorer** section on the Polkadot.js Apps interface and ensure that the **`LiquidityAdded`** event was emitted.

![Liquidity Added Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-07.webp)


Swap Assets

## Swap Assets


Swap from an Exact Amount of Tokens

### Swap from an Exact Amount of Tokens

The asset conversion pallet enables users to exchange a specific quantity of one asset for another in a designated liquidity pool by swapping them for an exact amount of tokens. It guarantees the user will receive at least a predetermined minimum amount of the second asset. This function increases trading predictability and allows users to conduct asset exchanges with confidence that they are assured a minimum return.

To swap assets for an exact amount of tokens, follow these steps:

1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface:

    1. Select **Developer** from the top menu.
    2. Click on **Extrinsics** from the dropdown menu.

    ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp)

2. Select extrinsic to swap assets:

    1. Select the **`AssetConversion`** pallet.
    2. Choose the **`swapExactTokensForTokens`** extrinsic from the list of available extrinsics.

    ![Swap From Exact Tokens Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-08.webp)

3. Fill in the required fields:

    1. **`path: Vec<StagingXcmV3MultiLocation>`**: An array of Multilocations representing the path of the swap. The first and last elements of the array are the input and output assets, respectively. In this case, the path consists of two elements:

        - **`0: StagingXcmV3MultiLocation`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents.

            ```javascript
            {
              parents: 0,
              interior: 'Here'
            }
            ```

        - **`1: StagingXcmV3MultiLocation`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies.

            ```javascript
            {
              parents: 0,
              interior: {
                X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }]
              }
            }
            ```

    2. **`amountOut`**: The exact amount of the second asset that the user wants to receive.
    3. **`amountInMax`**: The maximum amount of the first asset that the user is willing to swap.
    4. **`sendTo`**: The account to which the swapped assets will be sent.
    5. **`keepAlive`**: A boolean value that determines whether the pool should be kept alive after the swap.
    6. Click on **Submit Transaction** to swap assets for an exact amount of tokens.

    ![Swap For Exact Tokens Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-09.webp)

    !!! warning
        Ensure that the appropriate amount of tokens provided has been minted previously and is available in your account before adding liquidity to the pool.

    In this case, the intention is to swap 0.01 DOT token (u128 value of 100000000000 as it has 10 decimals) for 0.04 PPM token (u128 value of 400000000000 as it also has 10 decimals).

Signing and submitting the transaction will execute the swap. To verify execution, check the **Explorer** section on the Polkadot.js Apps interface and make sure that the **`SwapExecuted`** event was emitted.

![Swap From Exact Tokens Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-10.webp)


Swap to an Exact Amount of Tokens

### Swap to an Exact Amount of Tokens

Conversely, the Asset Conversion pallet comes with a function that allows users to trade a variable amount of one asset to acquire a precise quantity of another. It ensures that users stay within a set maximum of the initial asset to obtain the desired amount of the second asset. This provides a method to control transaction costs while achieving the intended result.

To swap assets for an exact amount of tokens, follow these steps:

1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface:

    1. Select **Developer** from the top menu.
    2. Click on **Extrinsics** from the dropdown menu.

    ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp)

2. Select extrinsic to swap tokens:

    1. Select the **`AssetConversion`** pallet.
    2. Choose the **`swapTokensForExactTokens`** extrinsic from the list of available extrinsics.

    ![Swap Tokens For Exact Tokens Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-11.webp)

3. Fill in the required fields:

    1. **`path: Vec<StagingXcmV3MultiLocation\>`**: An array of Multilocations representing the path of the swap. The first and last elements of the array are the input and output assets, respectively. In this case, the path consists of two elements:
        - **`0: StagingXcmV3MultiLocation`**: The Multilocation of the first asset in the pool. In this case, it is the PPM token, which the following Multilocation represents.

            ```javascript
            {
              parents: 0,
              interior: {
                X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }]
              }
            }
            ```

        - **`1: StagingXcmV3MultiLocation`**: The second asset's Multilocation within the pool. This refers to the DOT token, which the following Multilocation identifies.

            ```javascript
            {
              parents: 0,
              interior: 'Here'
            }
            ```

    2. **`amountOut`**: The exact amount of the second asset that the user wants to receive.
    3. **`amountInMax`**: The maximum amount of the first asset that the user is willing to swap.
    4. **`sendTo`**: The account to which the swapped assets will be sent.
    5. **`keepAlive`**: A boolean value that determines whether the pool should be kept alive after the swap.
    6. Click on **Submit Transaction** to swap assets for an exact amount of tokens.

    ![Swap Tokens For Exact Tokens Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-12.webp)

    !!! warning
        Before swapping assets, ensure that the tokens provided have been minted previously and are available in your account.

    In this case, the intention is to swap 0.01 DOT token (`u128` value of 100000000000 as it has ten decimals) for 0.04 PPM token (`u128` value of 400000000000 as it also has ten decimals).

Signing and submitting the transaction will execute the swap. To verify execution, check the **Explorer** section on the Polkadot.js Apps interface and make sure that the **`SwapExecuted`** event was emitted.

![Swap Tokens For Exact Tokens Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-13.webp)


Withdraw Liquidity from a Pool

## Withdraw Liquidity from a Pool

The Asset Conversion pallet provides the `removeLiquidity` extrinsic to remove liquidity from a pool. This function allows users to withdraw the liquidity they offered from a pool, returning the original assets. When calling this function, users specify the number of liquidity tokens (representing their share in the pool) they wish to burn. They also set minimum acceptable amounts for the assets they expect to receive back. This mechanism ensures that users can control the minimum value they receive, protecting against unfavorable price movements during the withdrawal process.

To withdraw liquidity from a pool, follow these steps:

1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface:

    1. Select **Developer** from the top menu.
    2. Click on **Extrinsics** from the dropdown menu.

    ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp)

2. Select extrinsic to withdraw liqudity from a pool:

    1. Select the **`AssetConversion`** pallet.
    2. Choose the **`removeLiquidity`** extrinsic from the list of available extrinsics.

    ![Remove Liquidity Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-14.webp)

3. Fill in the required fields:

    1. **`asset1`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents.

        ```javascript
        {
          parents: 0,
          interior: 'Here'
        }
        ```

    2. **`asset2`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies.

        ```javascript
        {
          parents: 0,
          interior: {
            X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }]
          }
        }
        ```

    3. **`lpTokenBurn`**: The number of liquidity tokens to burn.
    4. **`amount1MinReceived`**: The minimum amount of the first asset that the user expects to receive.
    5. **`amount2MinReceived`**: The minimum quantity of the second asset the user expects to receive.
    6. **`withdrawTo`**: The account to which the withdrawn assets will be sent.
    7. Click on **Submit Transaction** to withdraw liquidity from the pool.

    ![Remove Liquidity Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-15.webp)

    !!! warning
        Ensure that the tokens provided have been minted previously and are available in your account before withdrawing liquidity from the pool.

    In this case, the intention is to withdraw 0.05 liquidity tokens from the pool, expecting to receive 0.004 DOT token (`u128` value of 40000000000 as it has 10 decimals) and 0.04 PPM token (`u128` value of 400000000000 as it also has 10 decimals).

Signing and submitting the transaction will initiate the withdrawal of liquidity from the pool. To verify the withdrawal, check the **Explorer** section on the Polkadot.js Apps interface and ensure that the **`LiquidityRemoved`** event was emitted.

![Remove Liquidity Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-16.webp)


Test Environment Setup

## Test Environment Setup

To test the Asset Conversion pallet, you can set up a local test environment to simulate different scenarios. This guide uses Chopsticks to spin up an instance of Polkadot Asset Hub. For further details on using Chopsticks, please refer to the [Chopsticks documentation](/parachains/testing/fork-a-parachain/).

To set up a local test environment, execute the following command:

```bash
npx @acala-network/chopsticks \
--config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml
```

This command initiates a lazy fork of Polkadot Asset Hub, including the most recent block information from the network. For Kusama Asset Hub testing, simply switch out `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command.

You now have a local Asset Hub instance up and running, ready for you to test various asset conversion procedures. The process here mirrors what you'd do on MainNet. After completing a transaction on TestNet, you can apply the same steps to convert assets on MainNet.


Introduction

## Introduction

As outlined in the [Assets on Polkadot Hub Overview](/reference/polkadot-hub/assets/), Polkadot Hub supports two categories of assets: local and foreign. Local assets are created on Polkadot Hub and are identified by integer IDs. On the other hand, foreign assets, which originate outside of Polkadot Hub, are recognized by [Multilocations](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers).

When registering a foreign asset on Polkadot Hub, it's essential to notice that the process involves communication between two parachains. The Polkadot Hub chain will be the destination of the foreign asset, while the source parachain will be the origin of the asset. The communication between the two parachains is facilitated by the [Cross-Chain Message Passing (XCMP)](/parachains/interoperability/get-started/) protocol.

This guide will take you through the process of registering a foreign asset on Polkadot Hub.


Prerequisites

## Prerequisites

Polkadot Hub is a system parachain on a relay chain, such as [Polkadot](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpolkadot.api.onfinality.io%2Fpublic-ws#/explorer) or [Kusama](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fkusama.api.onfinality.io%2Fpublic-ws#/explorer). To interact with these parachains, you can use the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer) interface for:

- [Polkadot Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/explorer)
- [Kusama Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fsys.ibp.network%2Fstatemine#/explorer)

For testing purposes, you can also interact with the TestNet Polkadot Hub instance:

- [TestNet Polkadot Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpas-rpc.stakeworld.io%2Fassethub#/explorer)

Before you start, ensure that you have:

- Access to the Polkadot.js Apps interface, and you are connected to the desired chain.
- A parachain that supports the XCMP protocol to interact with the Polkadot Hub parachain.
- A funded wallet to pay for the transaction fees and subsequent registration of the foreign asset.

This guide will use Polkadot, its local Polkadot Hub instance, and the [Astar](https://astar.network/) parachain (`ID` 2006), as stated in the [Test Environment Setup](#test-environment-setup) section. However, the process is the same for other relay chains and their respective Polkadot Hub parachain, regardless of the network you are using and the parachain owner of the foreign asset.


Register a Foreign Asset

## Register a Foreign Asset


Polkadot Hub

### Polkadot Hub

To register a foreign asset on Polkadot Hub, follow these steps:

1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/) interface and connect to Polkadot Hub using the network selector in the top left corner.

      - Testing foreign asset registration is recommended on TestNet before proceeding to MainNet. If you haven't set up a local testing environment yet, consult the [Environment setup](#test-environment-setup) guide. After setting up, connect to the Local Node (Chopsticks) at `ws://127.0.0.1:8000`.
      - For live network operations, connect to Polkadot Hub. You can choose either Polkadot or Kusama Asset Hub from the dropdown menu, selecting your preferred RPC provider.

2. Navigate to the **Extrinsics** page:

      1. Click on the **Developer** tab from the top navigation bar.
      2. Select **Extrinsics** from the dropdown.

    ![Access to Developer Extrinsics section](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-01.webp)

3. Select the Foreign Assets pallet:

      3. Select the **`foreignAssets`** pallet from the dropdown list.
      4. Choose the **`create`** extrinsic.

    ![Select the Foreign Asset pallet](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-02.webp)

3. Fill out the required fields and click on the copy icon to copy the **encoded call data** to your clipboard. The fields to be filled are:

    - **id**: As this is a foreign asset, the ID will be represented by a Multilocation that reflects its origin. For this case, the Multilocation of the asset will be from the source parachain perspective.

        ```javascript
        { parents: 1, interior: { X1: [{ Parachain: 2006 }] } }
        ```

    - **admin**: Refers to the account that will be the admin of this asset. This account will be able to manage the asset, including updating its metadata. As the registered asset corresponds to a native asset of the source parachain, the admin account should be the sovereign account of the source parachain.

        The sovereign account can be obtained through [Substrate Utilities](https://www.shawntabrizi.com/substrate-js-utilities/).

        Ensure that **Sibling** is selected and that the **Para ID** corresponds to the source parachain. In this case, since the guide follows the test setup stated in the [Test Environment Setup](#test-environment-setup) section, the **Para ID** is `2006`.

        ![Get parachain sovereign account](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-03.webp)

    - **`minBalance`**: The minimum balance required to hold this asset.

    ![Fill out the required fields](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-04.webp)

    !!! tip
        If you need an example of the encoded call data, you can copy the following:
        ```
        0x3500010100591f007369626cd6070000000000000000000000000000000000000000000000000000a0860100000000000000000000000000
        ```


Source Parachain

### Source Parachain

With the encoded call data you generated in the previous section, you can take the following steps on the source parachain to complete the asset registration process:

1. Navigate to the **Developer > Extrinsics** section.
2. Create the extrinsic to register the foreign asset through XCM:

      1. Paste the **encoded call data** copied in the previous step.
      2. Click the **Submit Transaction** button.

    ![Register foreign asset through XCM](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-05.webp)

    This XCM call involves withdrawing DOT from the sibling account of the parachain, using it to initiate an execution. The transaction will be carried out with XCM as the origin kind, and will be a hex-encoded call to create a foreign asset on Polkadot Hub for the specified parachain asset multilocation. Any surplus will be refunded, and the asset will be deposited into the sibling account.

    !!! warning
        Note that the sovereign account on Polkadot Hub must have a sufficient balance to cover the XCM `BuyExecution` instruction. If the account does not have enough balance, the transaction will fail.

    If you want to have the whole XCM call ready to be copied, go to the **Developer > Extrinsics > Decode** section and paste the following hex-encoded call data:

    ```text
    0x6300330003010100a10f030c000400010000070010a5d4e81300010000070010a5d4e80006030700b4f13501419ce03500010100591f007369626cd607000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    ```

    Be sure to replace the encoded call data with the one you copied in the previous step.

After the transaction is successfully executed, the foreign asset will be registered on Polkadot Hub.


Asset Registration Verification

## Asset Registration Verification

To confirm that a foreign asset has been successfully accepted and registered on Polkadot Hub, you can navigate to the **Network > Explorer** section of the Polkadot.js Apps interface for Polkadot Asset Hub. You should be able to see an event that includes the following details:

![Asset registration event](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-06.webp)

In the image above, the **success** field indicates whether the asset registration was successful.


Test Environment Setup

## Test Environment Setup

To test the foreign asset registration process before deploying it on a live network, you can set up a local parachain environment. This guide uses Chopsticks to simulate that process. For more information on using Chopsticks, please refer to the [Chopsticks documentation](/parachains/testing/fork-a-parachain/).

To set up a test environment, run the following command:

```bash
npx @acala-network/chopsticks xcm \
--r polkadot \
--p polkadot-asset-hub \
--p astar
```

The preceding command will create a lazy fork of Polkadot as the relay chain, its Polkadot Hub instance, and the Astar parachain. The `xcm` parameter enables communication through the XCMP protocol between the relay chain and the parachains, allowing the registration of foreign assets on Polkadot Hub. For further information on the chopsticks usage of the XCMP protocol, refer to the [Replay and Dry Run XCMs using Chopsticks](/chain-interactions/send-transactions/interoperability/debug-and-preview-xcms/) guide.

After executing the command, the terminal will display output indicating the Polkadot relay chain, Polkadot Hub, and the Astar parachain are running locally and connected through XCM. You can access them individually via the Polkadot.js Apps interface.

- [Polkadot Relay Chain](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Flocalhost%3A8002#/explorer)
- [Polkadot Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Flocalhost%3A8000#/explorer)
- [Astar Parachain](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Flocalhost%3A8001#/explorer)


Introduction

## Introduction

As detailed in the [Assets on Polkadot Hub Overview](/reference/polkadot-hub/assets/) page, Polkadot Hub accommodates two types of assets: local and foreign. Local assets are those that were created in Polkadot Hub and are identifiable by an integer ID. On the other hand, foreign assets originate from a sibling parachain and are identified by a Multilocation.

This guide will take you through the steps of registering a local asset on Polkadot Hub.


Prerequisites

## Prerequisites

Before you begin, ensure you have access to the [Polkadot.js Apps](https://polkadot.js.org/apps/) interface and a funded wallet with DOT or KSM.

- For Polkadot Hub, you would need a deposit of 10 DOT and around 0.201 DOT for the metadata.
- For Kusama Hub, the deposit is 0.1 KSM and around 0.000669 KSM for the metadata.

You need to ensure that your Polkadot Hub account balance is a bit more than the sum of those two deposits, which should seamlessly account for the required deposits and transaction fees.


Register a Local Asset

## Register a Local Asset

To register a local asset on Polkadot Hub, follow these steps:

1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/) interface and connect to the Polkadot Asset Hub using the network selector in the top left corner.

      - You may prefer to test local asset registration on TestNet before registering the asset on a MainNet hub. If you still need to set up a local testing environment, review the [Environment setup](#test-setup-environment) section for instructions. Once the local environment is set up, connect to the Local Node (Chopsticks) available on `ws://127.0.0.1:8000`.
      - For the live network, connect to the **Asset Hub** parachain. Either Polkadot or Kusama Asset Hub can be selected from the dropdown list, choosing the desired RPC provider.

2. Click on the **Network** tab on the top navigation bar and select **Assets** from the dropdown list.

      ![Access to Polkadot Hub through Polkadot.JS](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-01.webp)

3. Now, you need to examine all the registered asset IDs. This step is crucial to ensure that the asset ID you are about to register is unique. Asset IDs are displayed in the **assets** column.

      ![Asset IDs on Polkadot Hub](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-02.webp)

4. Once you have confirmed that the asset ID is unique, click on the **Create** button on the top right corner of the page.

      ![Create a new asset](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-03.webp)

5. Fill in the required fields in the **Create Asset** form:

    1. **creator account**: The account to be used for creating this asset and setting up the initial metadata.
    2. **asset name**: The descriptive name of the asset you are registering.
    3. **asset symbol**: The symbol that will be used to represent the asset.
    4. **asset decimals**: The number of decimal places for this token, with a maximum of 20 allowed through the user interface.
    5. **minimum balance**: The minimum balance for the asset. This is specified in the units and decimals as requested.
    6. **asset ID**: The selected id for the asset. This should not match an already-existing asset id.
    7. Click on the **Next** button.

    ![Create Asset Form](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-04.webp)

6. Choose the accounts for the roles listed below:

    1. **admin account**: The account designated for continuous administration of the token.
    2. **issuer account**: The account that will be used for issuing this token.
    3. **freezer account**: The account that will be used for performing token freezing operations.
    4. Click on the **Create** button.

    ![Admin, Issuer, Freezer accounts](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-05.webp)

7. Click on the **Sign and Submit** button to complete the asset registration process.

    ![Sign and Submit](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-06.webp)


Verify Asset Registration

## Verify Asset Registration

After completing these steps, the asset will be successfully registered. You can now view your asset listed on the [**Assets**](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/assets) section of the Polkadot.js Apps interface.

![Asset listed on Polkadot.js Apps](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-07.webp)

!!! tip
    Take into consideration that the **Assets** section’s link may differ depending on the network you are using. For the local environment, enter `ws://127.0.0.1:8000` into the **Custom Endpoint** field.

In this way, you have successfully registered a local asset on the Polkadot Hub.

For an in-depth explanation about Polkadot Hub and its features, see the [Polkadot Hub](/chain-interactions/token-operations/convert-assets/) entry in the Polkadot Wiki.


Test Setup Environment

## Test Setup Environment

You can set up a local parachain environment to test the asset registration process before deploying it on the live network. This guide uses Chopsticks to simulate that process. For further information on chopsticks usage, refer to the [Chopsticks](/parachains/testing/fork-a-parachain/) documentation.

To set up a test environment, execute the following command:

```bash
npx @acala-network/chopsticks \
--config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml
```

The above command will spawn a lazy fork of Polkadot Hub with the latest block data from the network. If you need to test Kusama Hub, replace `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command.

A Polkadot Hub instance is now running locally, and you can proceed with the asset registration process. Note that the local registration process does not differ from the live network process. Once you have a successful TestNet transaction, you can use the same steps to register the asset on MainNet.


Support Channels

## Support Channels

Use one of the channels below to get live technical support or ask questions.

-   :simple-telegram:{ .sub } **Telegram: Polkadot Developer Support**

 **Who’s there:** DevRel team and active developer community.

 **Response time:** Within **2 business days (usually faster)**.

 **Topics:** Any developer-related question is welcome.

    👉 [Join Telegram](https://t.me/substratedevs)

-   :simple-discord:{ .sub } **Discord: Polkadot Official Server**

 **Smart contracts:** Ask in `#solidity-smart-contracts` and `#ink_smart-contracts`.

 **General developer support:** Ask in `#solidity-smart-contracts`.

 **Response time:** Within **1 business day (usually faster)**.

    👉 [Join Discord](https://polkadot-discord.w3f.tools/)

-   :simple-matrix:{ .sub } **Matrix: Polkadot Developer Support**

 **Who’s there:** Parity, W3F, DevRel, and community contributors.

 **Response time:** Within **1 business day (usually faster)**.

 **Topics:** Full-spectrum developer support.

 Bridged with Telegram (all messages synced).

    👉 [Join Matrix](https://matrix.to/#/#substratedevs:matrix.org)


Community Resources

## Community Resources

-   :fontawesome-brands-stack-exchange:{ .sub } **Stack Exchange**

 Browse commonly asked technical questions.

 Ask your own and get detailed responses from experienced devs.

    👉 [Visit Polkadot Stack Exchange](https://substrate.stackexchange.com/)

-   :simple-reddit:{ .sub } **Reddit: r/Polkadot**

 General discussions and community perspectives.

 Developer questions are welcome — just tag them appropriately.

    👉 [Visit r/Polkadot](https://www.reddit.com/r/Polkadot/)

-   :simple-youtube:{ .sub } **YouTube: @PolkadotNetwork**

 Developer tutorials.

 Ecosystem interviews.

 Event recordings and walkthroughs.

    👉 [Watch on YouTube](https://www.youtube.com/@PolkadotNetwork)

-   :fontawesome-brands-x-twitter:{ .sub } **X (Twitter): Official Accounts**

    - **[@PolkadotDevs](https://x.com/PolkadotDevs)**: Updates for developers.
    - **[@Polkadot](https://x.com/Polkadot)**: Network-wide news.
    - **[@Kusamanetwork](https://x.com/kusamanetwork)**: Kusama-specific updates.
    - **[@Web3Foundation](https://x.com/web3foundation)**: Grants, research, and ecosystem programs.

-   :fontawesome-brands-x-twitter:{ .sub } **X (Twitter): Community Accounts**

    - **[@PolkadotDeploy](https://x.com/PolkadotDeploy)**: News from the deployment portal and tooling updates.

-   :material-forum:{ .sub } **Polkadot Forum**

 Join community discussions around the direction of the ecosystem.

    👉 [Visit the Polkadot Forum](https://forum.polkadot.network/)

-   :material-vote:{ .sub } **Polkassembly: OpenGov**

 Explore and vote on governance proposals for Polkadot and Kusama.

 Help shape the future of the network.

    👉 [Explore on Polkassembly](https://polkadot.polkassembly.io/)

-   :material-vote:{ .sub } **Subsquare: OpenGov**

 Track, discuss, and vote on Polkadot OpenGov proposals.

 Stay informed on governance activity across the network.

    👉 [Explore on Subsquare](https://polkadot.subsquare.io/)


AI Resources

## AI Resources

<div class="grid cards support" markdown>

-   :fontawesome-solid-robot:{ .sub } **AI Resources**

    Access documentation structured and optimized for use with large language models (LLMs) and AI tools. These resources help build AI assistants, power code search, or enable custom tooling trained on Polkadot’s documentation.

    👉 [Access LLM Files](/ai-resources/)

</div>


Introduction

## Introduction

The Polkadot network relies on various types of nodes to maintain security, provide data access, and produce blocks. This section covers everything you need to know about running infrastructure for the Polkadot ecosystem.

Whether you want to provide RPC endpoints for applications, produce blocks for a parachain, or secure the relay chain as a validator, this guide will help you understand your options and get started.


Node Types

## Node Types


RPC Nodes

### RPC Nodes

RPC nodes provide API access to blockchain data without participating in consensus. They are essential infrastructure for:

- **Applications and dApps**: Query blockchain state and submit transactions.
- **Block explorers**: Index and display blockchain data.
- **Wallets**: Check balances and broadcast transactions.
- **Development**: Test and debug applications.

RPC nodes can be run for both the relay chain and parachains, with varying levels of data retention:

- **Pruned nodes**: Keep recent state and a limited number of finalized blocks. Suitable for most applications that only need the current state and recent history. More efficient in terms of storage and sync time.
- **Archive nodes**: Maintain complete historical state and all blocks since genesis. Required for block explorers, analytics platforms, or applications that need to query historical data at any point in time.

**Transaction Broadcasting**: RPC nodes play a crucial role in transaction submission and propagation. When a client submits a transaction via RPC methods like `author_submitExtrinsic`, the node validates the transaction format, adds it to its local transaction pool, and broadcasts it across the P2P network. Block producers (collators or validators) then pick up these transactions from their pools for inclusion in blocks. This makes RPC nodes the primary gateway for users and applications to interact with the blockchain.


Collators

### Collators

Collators are block producers for parachains. They perform critical functions:

- **Collect transactions**: Aggregate user transactions into blocks.
- **Produce blocks**: Create parachain block candidates.
- **Generate and package PoV**: Generate the Proof-of-Validity containing the state transition proof and necessary witness data for validation.
- **Submit to validators**: Send block candidates and PoVs to relay chain validators.

Unlike validators, collators do not provide security guarantees—that responsibility lies with the relay chain validators. However, collators are essential for parachain liveness and censorship resistance.


Validators

### Validators

Validators secure the Polkadot relay chain through [Nominated Proof of Stake (NPoS)](https://wiki.polkadot.com/learn/learn-staking/#nominated-proof-of-stake-npos). They:

- **Validate blocks**: Verify parachain blocks and relay chain transactions.
- **Participate in consensus**: Run [BABE](/reference/polkadot-hub/consensus-and-security/pos-consensus/#block-production-babe) and [GRANDPA](/reference/polkadot-hub/consensus-and-security/pos-consensus/#finality-gadget-grandpa) protocols.
- **Earn rewards**: Receive staking rewards for honest behavior.
- **Risk slashing**: Face penalties for misbehavior or downtime.

Running a validator requires significant technical expertise, reliable infrastructure, and a stake of DOT tokens.


Next Steps

## Next Steps

<div class="grid cards" markdown>

-   **Run RPC Nodes**

    ---

    Provide API access for applications, explorers, and wallets.

    [:octicons-arrow-right-24: Run a Node](/node-infrastructure/run-a-node/polkadot-hub-rpc/)

-   **Run a Collator**

    ---

    Produce blocks for system parachains or your own parachain.

    [:octicons-arrow-right-24: Run a Collator](/node-infrastructure/run-a-collator/)

-   **Run a Validator**

    ---

    Secure the relay chain and earn staking rewards.

    [:octicons-arrow-right-24: Run a Validator](/node-infrastructure/run-a-validator/requirements/)

</div>


Introduction

## Introduction

Block-producing collators are the backbone of system parachain operations. Unlike RPC or archive nodes, which maintain state, collators actively produce blocks and submit them to relay chain validators for inclusion. They ensure network liveness, censorship resistance, and cross-chain message processing.

Collators maintain fully synced relay chain and parachain nodes, aggregate transactions into blocks, create parachain block candidates, generate state transition proofs (Proof-of-Validity), and send block candidates to relay chain validators. They also enable cross-chain message handling via XCM. While critical for liveness, collators do not secure the network—security is provided by relay chain validators through the [ELVES protocol](https://wiki.polkadot.com/learn/learn-parachains-protocol/).

This guide explains how to set up a collator for Polkadot system parachains, covering all key requirements, setting up and registering session keys, and meeting governance approval or invulnerables-list criteria (required for system parachains; non-system parachains may be more permissionless).


Prerequisites

## Prerequisites


Hardware Requirements

### Hardware Requirements

Block-producing collators require robust hardware for reliable operation, including the following:

- **CPU**: 4+ cores (8+ cores recommended for optimal performance)
- **Memory**: 32 GB RAM minimum (64 GB recommended)
- **Storage**:
    - 200+ GB NVMe SSD (with pruning enabled for both parachain and relay chain)
    - Fast disk I/O is critical for block production performance
- **Network**:
    - Public IP address
    - 100+ Mbps connection; a stable connection is critical
    - Open ports:
        - **30333**: Parachain P2P
        - **30334**: Relay chain P2P

!!! warning "Uptime is critical"
    Consider redundancy and monitoring to maintain block production reliability.


Software Requirements

### Software Requirements

Required software:

- **Operating system**: Ubuntu 22.04 LTS (recommended) or similar Linux distribution
- **[Docker](https://www.docker.com/get-started/)**: Required for obtaining binaries and running containers


Account Requirements

### Account Requirements

??? interface "Need to create an account?"

    You can generate an account by taking the following steps:

    1. Generate an account key with the `sr25519` scheme using the following command:

        ```bash
        docker run -it parity/subkey:latest generate --scheme sr25519
        ```

        The output will be similar to the following:

        docker run -it parity/subkey:latest generate --scheme sr25519

Secret phrase:       embody rail hour peanut .... badge syrup luggage canvas
            Network ID:        substrate
            Secret seed:       0x6498dd3416c491406e2c8283c76760ce4ca018478888b42315e7718778f2c2e1
            Public key (hex):  0x2202210357e49390d4f8d868da983940fe220a0a0e00bc6feaeda462aa031810
            Account ID:        0x2202210357e49390d4f8d868da983940fe220a0a0e00bc6feaeda462aa031810
            Public key (SS58): 5CqJ7n72GvvF5ZzUT2HMj83KyDje4n8sXR8kuiK8HWtfDktF
            SS58 Address:      5CqJ7n72GvvF5ZzUT2HMj83KyDje4n8sXR8kuiK8HWtfDktF

    2. Save the following items displayed in the output:
        - Secret phrase (seed) - Keep this secure!
        - Public key (hex)
        - Account ID
        - SS58 Address

        !!! warning

            Store the secret phrase securely. Never share it. Consider using a hardware wallet for production collators.

Your account must meet the following requirements:

- **Funded account**: For on-chain transactions and potential bonding

You will also need the following, which are generated or configured later in this guide:

- **Session keys**: For collator identification (generated after node setup)
- **Node key**: For stable P2P peer ID (recommended)


Install Dependencies

## Install Dependencies

This guide provides two deployment options. Select the option that best fits your needs:

- **Docker**: Best for simpler setup and maintenance
- **systemd**: Best for production environments requiring more control

=== "Docker"

    1. Pull the Polkadot Parachain Docker image using the latest stable tag on [Docker Hub](https://hub.docker.com/r/parity/polkadot-parachain/tags):

        ```bash
        docker pull parity/polkadot-parachain:stable2603
        ```

    2. Verify the installation:

        ```bash
        docker run --rm parity/polkadot-parachain:stable2603 --version
        ```

=== "systemd"

    1. Download the `polkadot-parachain` binary using the latest stable [Polkadot SDK release](https://github.com/paritytech/polkadot-sdk/releases):

        ```bash
        wget https://github.com/paritytech/polkadot-sdk/releases/download/polkadot-stable2603/polkadot-parachain
        ```

    2. Make it executable and move it to your system path:

        ```bash
        chmod +x polkadot-parachain
        sudo mv polkadot-parachain /usr/local/bin/
        sudo chown root:root /usr/local/bin/polkadot-parachain
        ```

    3. Verify installation:

        ```bash
        polkadot-parachain --version
        ```


Generate Node Key

## Generate Node Key

Generating a stable node key enables a consistent peer ID across the network. Follow these steps to generate a node key:

1. Create a directory for node data:

    ```bash
    sudo mkdir -p /var/lib/polkadot-collator
    ```

2. Generate your node key using Docker:

    ```bash
    docker run -it parity/subkey:latest generate-node-key > /var/lib/polkadot-collator/node.key
    ```

3. Locate your peer ID in the displayed output. It will be similar to the following example:

    ```bash
    12D3KooWExcVYu7Mvjd4kxPVLwN2ZPnZ5NyLZ5ft477wqzfP2q6E
    ```

Be sure to save the peer ID for future reference.


Obtain Chain Specification

## Obtain Chain Specification

Download the chain specification for your target system parachain using one of the following options:

=== "Download from Chainspec Collection (Recommended)"

    Download the chain specification directly using `curl`. For example, to download the Asset Hub Polkadot chain spec:

    ```bash
    curl -sL -o chain-spec.json \
      https://paritytech.github.io/chainspecs/polkadot/parachain/asset-hub/chainspec.json
    ```

    For other system parachains, find the correct URL in the [Chainspec Collection](https://paritytech.github.io/chainspecs/) under the [**List of Chainspecs**](https://paritytech.github.io/chainspecs/#list-of-chainspecs).

=== "Build Chain Spec from Runtime"

    Follow these steps to build a chainspec from the runtime:

    1. Clone the runtimes repository and navigate into it:

        ```bash
        git clone https://github.com/polkadot-fellows/runtimes.git
        cd runtimes
        ```

    2. Build the desired runtime. Use the following command for Polkadot Hub:

        ```bash
        cargo build --release -p asset-hub-polkadot-runtime
        ```

    3. Install the `chain-spec-builder` dependency:

        ```bash
        cargo install --locked staging-chain-spec-builder@14.0.0
        ```

    4. Finally, generate the chain spec:

        ```bash
        chain-spec-builder create \
            --relay-chain polkadot \
            --para-id 1000 \
            --runtime target/release/wbuild/asset-hub-polkadot-runtime/asset_hub_polkadot_runtime.compact.compressed.wasm \
            named-preset production > chain-spec.json
        ```

        ??? tip "System Parachain Para IDs"

            - **Polkadot Hub**: 1000
            - **Bridge Hub**: 1002
            - **People Chain**: 1004
            - **Coretime Chain**: 1005


Run the Collator

## Run the Collator

Using your preferred deployment method, take the following steps to set up and run your collator:

=== "Docker"

    1. Create a directory for collator data and copy the chain spec:

        ```bash
        mkdir -p collator-data
        cp chain-spec.json collator-data/
        cp /var/lib/polkadot-collator/node.key collator-data/
        ```

    2. Launch the collator using Docker:

        ```bash
        docker run -d --name polkadot-collator --restart unless-stopped \
          -p 30333:30333 \
          -p 30334:30334 \
          -p 9944:9944 \
          -p 9615:9615 \
          -v $(pwd)/collator-data:/data \
          -v $(pwd)/chain-spec.json:/chain-spec.json \
          parity/polkadot-parachain:stable2603 \
          --collator \
          --chain=/chain-spec.json \
          --base-path=/data \
          --port=30333 \
          --rpc-port=9944 \
          --prometheus-port=9615 \
          --prometheus-external \
          --node-key-file=/data/node.key \
          --name="INSERT_YOUR_COLLATOR_NAME" \
          --blocks-pruning=256 \
          --state-pruning=256 \
          --database=paritydb \
          -- \
          --chain=polkadot \
          --port=30334 \
          --sync=fast \
          --blocks-pruning=256 \
          --state-pruning=256 \
          --database=paritydb \
          --pool-limit=0 \
          --rpc-port=0
        ```

    3. View logs to monitor sync progress:

        ```bash
        docker logs -f polkadot-collator
        ```

=== "systemd"

    1. Create a dedicated user:

        ```bash
        sudo useradd -r -s /bin/bash polkadot
        ```

    2. Copy your chain spec to the directory:

        ```bash
        sudo cp chain-spec.json /var/lib/polkadot-collator/
        ```

    3. Set permissions:

        ```bash
        sudo chown -R polkadot:polkadot /var/lib/polkadot-collator
        ```

    4. Create a systemd service file:

        ```bash
        sudo nano /etc/systemd/system/polkadot-collator.service
        ```

    5. Add the following configuration:

        ```ini title="systemd/system/polkadot-collator.service"
        [Unit]
        Description=Polkadot System Parachain Collator
        After=network.target

        [Service]
        Type=simple
        User=polkadot
        Group=polkadot
        WorkingDirectory=/var/lib/polkadot-collator

        ExecStart=/usr/local/bin/polkadot-parachain \
          --collator \
          --chain=/var/lib/polkadot-collator/chain-spec.json \
          --base-path=/var/lib/polkadot-collator \
          --port=30333 \
          --rpc-port=9944 \
          --prometheus-port=9615 \
          --node-key-file=/var/lib/polkadot-collator/node.key \
          --name="INSERT_YOUR_COLLATOR_NAME" \
          --blocks-pruning=256 \
          --state-pruning=256 \
          --database=paritydb \
          -- \
          --chain=polkadot \
          --port=30334 \
          --sync=fast \
          --blocks-pruning=256 \
          --state-pruning=256 \
          --database=paritydb \
          --pool-limit=0 \
          --rpc-port=0

        Restart=always
        RestartSec=10
        LimitNOFILE=65536

        [Install]
        WantedBy=multi-user.target
        ```

    6. Start the service:

        ```bash
        sudo systemctl daemon-reload
        sudo systemctl enable polkadot-collator
        sudo systemctl start polkadot-collator
        ```

    7. Check the status:

        ```bash
        sudo systemctl status polkadot-collator
        ```

    8. View logs:

        ```bash
        sudo journalctl -u polkadot-collator -f
        ```

??? interface "Configuration Arguments"

    - **`--collator`**: Enables block production mode.
    - **`--node-key-file`**: Uses the generated node key for stable peer ID.
    - **`--name`**: Your collator name (visible in [telemetry](https://telemetry.polkadot.io/)).
    - **`--blocks-pruning=256`**: Keeps the last 256 blocks.
    - **`--state-pruning=256`**: Keeps the state history of the last 256 blocks.
    - **`--database=paritydb`**: Uses ParityDB for better performance.
    - **`--sync=fast`**: Fast sync mode for the relay chain.
    - **`--pool-limit=0`**: Disables transaction pool on relay chain (not needed for collators).
    - **`--rpc-port=0` (relay chain)**: Disables RPC on the embedded relay chain node (not needed for collators).

Your collator must sync both the relay chain and parachain before producing blocks. The relay chain uses fast sync to speed up synchronization. Overall sync time depends on:

- Network bandwidth
- Disk I/O speed
- Current chain size

!!! warning

    Do not proceed with registration until both chains are fully synced. Monitor sync progress using the log viewing commands in the [Log Management](#commands-for-log-management) section.


Generate Session Keys

## Generate Session Keys

Session keys are cryptographic keys used by your collator node to sign authorship information when producing blocks. They uniquely identify your collator on the network and must be registered on-chain before your collator can participate in block production.

Once your node is fully synced, use the following command to generate session keys via RPC:

```bash
curl -H "Content-Type: application/json" \
  -d '{"id":1, "jsonrpc":"2.0", "method": "author_rotateKeys", "params":[]}' \
  http://localhost:9944
```

This command returns session keys as a hex string in the terminal. You must save these session keys as you'll need them for on-chain registration. As session keys are stored in the node's database, if you wipe the database, you'll also need to generate new keys.


Register Collator for Selection

## Register Collator for Selection

System parachains use different mechanisms for selecting collators. A quick breakdown of each mechanism is as follows:

| Method                   | How it Works                                                                                | Requirements                                                     |
|--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------|
| **Invulnerables list**   | Fixed list defined through governance. Most common for system parachains.                                                                                | Permissioned via governance                                      |
| **On-chain selection**   | Runtime automatically selects eligible collators. Some parachains use [pallet-collator-selection](https://paritytech.github.io/polkadot-sdk/master/pallet_collator_selection/index.html). | Semi-permissionless (criteria-based; may require bonding tokens) |
| **Fellowship decisions** | Technical fellowship may manage some system parachain collators.                                                                                | Permissioned via Fellowship                                      |


Registration Process

### Registration Process

Collator registration authorizes your node to produce blocks on the network. The parachain's collator selection mechanism uses this on-chain registration to determine which nodes are eligible to author blocks.

The registration process varies by system parachain. General steps include the following:

1. Check the existing collators for your target parachain:
    1. Navigate to Polkadot.js Apps and connect to your system parachain.
    2. Locate **Developer > Chain State**.
    3. Query **`collatorSelection.invulnerables()`**.

    ![](/images/node-infrastructure/run-a-collator/run-a-collator-01.webp)

2. Prepare a governance proposal for invulnerables-based selection, including the following information:

    - **Draft proposal**: Explain why you should be added as a collator.
    - **Technical details**: Provide your session keys and account ID.
    - **Infrastructure**: Describe your hardware and monitoring setup.
    - **Experience**: Detail your relevant experience.

    Submit the proposal to the relevant governance channels.

3. Once approved (or if using on-chain selection), follow these steps to register session keys using Polkadot.js Apps:

    1. Locate **Developer > Extrinsics**.
    2. Select your account.
    3. Choose the **`session.setKeys`** extrinsic.
    4. Enter the following information:
        - **`keys`**: Your session keys (from `author_rotateKeys`)
        - **`proof`**: 0x00 (typically)
    5. Click **Submit Transaction** and sign the transaction.

    ![](/images/node-infrastructure/run-a-collator/run-a-collator-02.webp)

4. (Optional - primarily for non-system parachains) If the parachain uses on-chain bonding for collator selection, register as a candidate using Polkadot.js Apps:

    !!! note
        Most system parachains use invulnerables lists exclusively and do not require this step. Skip to step 5 if you're running a collator for a system parachain.

    1. Locate **Developer > Extrinsics**.
    2. Select your account.
    3. Select `collatorSelection.registerAsCandidate`.
    4. Click **Submit Transaction** and sign the transaction. The required bond amount will be automatically reserved from your account based on the pallet's configured `CandidacyBond`.

    ![](/images/node-infrastructure/run-a-collator/run-a-collator-03.webp)

5. For system parachains using invulnerables lists, await governance approval for your proposal. Once approved, your collator is added to the invulnerables list and will begin producing blocks in the next session or era.

6. Verify your collator is active by monitoring logs for block production messages like "Prepared block for proposing" and "Imported #123". See the [Log Management](#commands-for-log-management) section for commands for log viewing.


Commands for Node Management

## Commands for Node Management

Use the following commands to manage your node:

=== "Docker"

    - **Stop container**:

        ```bash
        docker stop polkadot-collator
        ```

    - **Start container**:

        ```bash
        docker start polkadot-collator
        ```

    - **Remove container**:

        ```bash
        docker rm polkadot-collator
        ```

=== "systemd"

    - **Check status**:

        ```bash
        sudo systemctl status polkadot-collator
        ```

    - **Stop service**:

        ```bash
        sudo systemctl stop polkadot-collator
        ```

    - **Enable service**:

        ```bash
        sudo systemctl enable polkadot-collator
        ```

    - **Start service**:

        ```bash
        sudo systemctl start polkadot-collator
        ```


Commands for Log Management

## Commands for Log Management

Efficient log management is essential to ensure collator performance and uptime. Use the following commands to help you manage logs to monitor and maintain your collator:

=== "Docker"

    - **View logs**:

        ```bash
        docker logs -f polkadot-collator
        ```

    - **View recent logs (last 100 lines)**:

        ```bash
        docker logs --tail 100 polkadot-collator
        ```

    - **Filter for errors**:

        ```bash
        docker logs polkadot-collator 2>&1 | grep -i error
        ```

    - **Filter for block production**:

        ```bash
        docker logs polkadot-collator 2>&1 | grep -i "imported"
        ```

=== "systemd"

    - **View recent logs**:

        ```bash
        sudo journalctl -u polkadot-collator -n 100
        ```

    - **Follow logs in real-time**:

        ```bash
        sudo journalctl -u polkadot-collator -f
        ```

    - **Filter for errors**:

        ```bash
        sudo journalctl -u polkadot-collator | grep -i error
        ```

    - **Filter for block production**:

        ```bash
        sudo journalctl -u polkadot-collator | grep -i "imported"
        ```


Database Maintenance

## Database Maintenance

Check database size periodically using the commands for your selected setup:

=== "Docker"

    ```bash
    # Replace with your mounted data directory path
    du -sh ./collator-data
    ```

=== "systemd"

    ```bash
    du -sh /var/lib/polkadot-collator
    ```

The collator node automatically prunes based on configuration.


Updates and Upgrades

## Updates and Upgrades

Updates or upgrades can happen on either the runtime or client. Runtime upgrades are automatically applied via on-chain governance and do not require any manual action on your part. Client upgrades do require a manual binary update process performed via terminal commands as follows:

=== "Docker"

    1. Stop the service:

        ```bash
        sudo systemctl stop polkadot-collator
        ```

    2. Backup data (recommended):

        ```bash
        sudo cp -r /var/lib/polkadot-collator /var/lib/polkadot-collator.backup
        ```

    3. Pull the new Docker image:

        ```bash
        docker pull parity/polkadot-parachain:<NEW_TAG>
        ```

    4. Update the image tag in your systemd service file:

        ```bash
        sudo nano /etc/systemd/system/polkadot-collator.service
        ```

    5. Reload systemd and restart the service:

        ```bash
        sudo systemctl daemon-reload
        sudo systemctl start polkadot-collator
        ```

    6. Verify the service is running:

        ```bash
        sudo systemctl status polkadot-collator
        ```

=== "systemd"

    1. Stop the service:

        ```bash
        sudo systemctl stop polkadot-collator
        ```

    2. Backup data (recommended):

        ```bash
        sudo cp -r /var/lib/polkadot-collator /var/lib/polkadot-collator.backup
        ```

    3. Download the new binary from [GitHub releases](https://github.com/paritytech/polkadot-sdk/releases):

        ```bash
        wget https://github.com/paritytech/polkadot-sdk/releases/download/INSERT_NEW_VERSION/polkadot-parachain
        chmod +x polkadot-parachain
        sudo mv polkadot-parachain /usr/local/bin/
        ```

    4. Verify `polkadot-parachain` version to confirm successful update:

        ```bash
        polkadot-parachain --version
        ```

    5. Restart the service:

        ```bash
        sudo systemctl start polkadot-collator
        ```

    6. Verify the service is running:

        ```bash
        sudo systemctl status polkadot-collator
        ```


Conclusion

## Conclusion

Running a collator node is essential for parachain operation and network security. By following this guide, you have set up a production-ready collator that:

- Produces blocks for your parachain and maintains network consensus.
- Implements comprehensive security measures to protect keys and operations.
- Supports robust monitoring and alerting for reliable performance.
- Follows best practices for both Docker and systemd deployments.

As a collator operator, you play a vital role in your parachain's infrastructure. Regular maintenance, security updates, and monitoring will ensure your collator continues to perform reliably. Stay engaged with your parachain community and keep up with updates to maintain optimal performance and security.


Introduction

## Introduction

A parachain RPC node provides direct access to a specific parachain on the Polkadot network, enabling developers and applications to interact with its assets, governance, cross-chain messages, and more. Running your own node also supports essential infrastructure tasks, such as block indexing and compatibility with Polkadot SDK tools.

Through the parachain RPC (WebSocket port 9944, HTTP port 9933), your node acts as the bridge between the parachain and applications. This page walks through setting up a node from scratch, covering hardware requirements and deployment options using Docker or systemd.


Prerequisites

## Prerequisites


Hardware Requirements

### Hardware Requirements

RPC nodes serving production traffic require robust hardware:

- **CPU**: 8+ cores; 16+ cores for high traffic
- **Memory**: 64 GB RAM minimum; 128 GB recommended for high traffic
- **Storage**: Storage requirements vary by parachain. Fast NVMe I/O is critical for RPC query performance
    - **System parachains**: [Snapshots](https://snapshots.polkadot.io/) _may_ be available
        - **Archive node (complete history)**: Using snapshots, expected storage requirements (including ~822 GB for the pruned relay chain) are:
            - **Asset Hub**: ~1.2 TB
            - **Bridge Hub**: ~1.1 TB
            - **Collectives**: ~1 TB
            - **People Chain**: ~900 GB
            - **Coretime**: ~900 GB
        - **Pruned node (recent state)**: ~200 GB total for both parachain and relay chain
    - **Non-system parachains**: Consult the parachain team or documentation, then add ~822 GB for the pruned relay chain
- **Network**:
    - Public IP address
    - Stable internet connection with sufficient bandwidth
    - 1 Gbps connection for high traffic scenarios
    - Consider DDoS protection and rate limiting for production deployments
    - Open ports:
        - **30333**: Parachain P2P
        - **30334**: Relay chain P2P
        - **9944**: Polkadot SDK WebSocket RPC
        - **9933**: Polkadot SDK HTTP RPC

!!! note
    For development or low-traffic scenarios, you can reduce these requirements proportionally. Consider using a reverse proxy ([nginx](https://nginx.org/), [Caddy](https://caddyserver.com/)) for production deployments.


Software Requirements

### Software Requirements

Required software:

- **Operating system**: Ubuntu 22.04 LTS (recommended) or similar Linux distribution
- **[Docker](https://www.docker.com/get-started/)**: Required for obtaining binaries and running containers
- **[rclone](https://rclone.org/downloads/)**: (Optional but recommended) Command-line program for managing files on cloud storage


Obtain the Chain Specification

## Obtain the Chain Specification

To run an RPC node for a parachain, you need its chain specification file. This JSON file defines the network parameters, genesis state, and bootnodes. The process for obtaining the chain spec may differ depending on whether you’re running a system parachain or a regular parachain.


System Parachains

### System Parachains

System parachain chain specs are available from multiple sources:

- **[Chainspec Collection](https://paritytech.github.io/chainspecs/)**: (Recommended) Choose a file to download from the **List of Chainspecs** section.
- **[Polkadot SDK repository](https://github.com/paritytech/polkadot-sdk)**: Download directly from the Polkadot SDK repository:

    ```bash
    # Example for People Chain
    curl -L https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/cumulus/parachains/chain-specs/people-polkadot.json -o chain-spec.json
    ```


Other Parachains

### Other Parachains

For non-system parachains, check the parachain's documentation for official chain specification files.


Spin Up a Node

## Spin Up a Node

Choose the deployment option that fits your project, and follow the steps in the appropriate tab to complete setup:

- **Docker**: Best for simpler set up and maintenance
- **systemd**: Best for production environments requiring more control

This guide uses **People Chain** as an example. To set up a different parachain, replace the chain spec file, snapshot path, and chain name with the corresponding values for your target parachain.

System parachain details:

| System Parachain   | Para ID | Chain Spec File            | Snapshot Path                          |
|--------------------|---------|----------------------------|----------------------------------------|
| **Bridge Hub**     | 1002    | `bridge-hub-polkadot.json` | `polkadot-bridge-hub-paritydb-archive` |
| **People Chain**   | 1004    | `people-polkadot.json`     | `polkadot-people-rocksdb-archive`      |
| **Coretime Chain** | 1005    | `coretime-polkadot.json`   | `polkadot-coretime-rocksdb-archive`    |

=== "Docker"

    1. Download your parachain's chain specification as described in [Obtain the Chain Specification](#obtain-the-chain-specification).

    2. (Optional but recommended) Download pre-synced [snapshots](https://snapshots.polkadot.io/) to cut initial sync time from days to hours:

        !!! note
            Snapshots are available for system parachains and the Polkadot relay chain. For other parachains, check with the parachain team for snapshot availability or sync from genesis.

        1. Create new directories:

            ```bash
            mkdir -p my-node-data/chains/people-polkadot/db
            mkdir -p my-node-data/chains/polkadot/db
            ```

        2. Download and save the archive parachain snapshot:

            ```bash
            # Check https://snapshots.polkadot.io/ for the latest snapshot URL
            export SNAPSHOT_URL_PARACHAIN="https://snapshots.polkadot.io/polkadot-people-rocksdb-archive/INSERT_LATEST"

            rclone copyurl $SNAPSHOT_URL_PARACHAIN/files.txt files.txt
            rclone copy --progress --transfers 20 \
              --http-url $SNAPSHOT_URL_PARACHAIN \
              --no-traverse --http-no-head --disable-http2 \
              --inplace --no-gzip-encoding --size-only \
              --retries 6 --retries-sleep 10s \
              --files-from files.txt :http: my-node-data/chains/people-polkadot/db/

            rm files.txt
            ```

            ??? interface "rclone parameters"

                - **`--transfers 20`**: Uses 20 parallel transfers for faster download
                - **`--retries 6`**: Automatically retries failed transfers up to 6 times
                - **`--retries-sleep 10s`**: Waits 10 seconds between retry attempts
                - **`--size-only`**: Only transfers if sizes differ (prevents unnecessary re-downloads)

        3. Repeat the process for the pruned relay chain snapshot:

            ```bash
            # Check https://snapshots.polkadot.io/ for the latest snapshot URL
            export SNAPSHOT_URL_RELAY="https://snapshots.polkadot.io/polkadot-rocksdb-prune/INSERT_LATEST"

            rclone copyurl $SNAPSHOT_URL_RELAY/files.txt files.txt
            rclone copy --progress --transfers 20 \
              --http-url $SNAPSHOT_URL_RELAY \
              --no-traverse --http-no-head --disable-http2 \
              --inplace --no-gzip-encoding --size-only \
              --retries 6 --retries-sleep 10s \
              --files-from files.txt :http: my-node-data/chains/polkadot/db/

            rm files.txt
            ```

    3. Launch the parachain node using the official [Parity Docker image](https://hub.docker.com/r/parity/polkadot-parachain):

        === "Archive"

            ```bash
            docker run -d --name people-chain-rpc --restart unless-stopped \
              -p 9944:9944 \
              -p 9933:9933 \
              -p 9615:9615 \
              -p 30334:30334 \
              -p 30333:30333 \
              -v $(pwd)/people-polkadot.json:/people-polkadot.json \
              -v $(pwd)/my-node-data:/data \
              parity/polkadot-parachain:stable2603 \
              --name=PeopleChainRPC \
              --base-path=/data \
              --chain=/people-polkadot.json \
              --prometheus-external \
              --prometheus-port 9615 \
              --unsafe-rpc-external \
              --rpc-port=9944 \
              --rpc-cors=all \
              --rpc-methods=safe \
              --rpc-max-connections=1000 \
              --state-pruning=archive \
              --blocks-pruning=archive \
              -- \
              --base-path=/data \
              --chain=polkadot \
              --state-pruning=256 \
              --blocks-pruning=256 \
              --rpc-port=0
            ```

        === "Pruned"

            ```bash
            docker run -d --name people-chain-rpc --restart unless-stopped \
              -p 9944:9944 \
              -p 9933:9933 \
              -p 9615:9615 \
              -p 30334:30334 \
              -p 30333:30333 \
              -v $(pwd)/people-polkadot.json:/people-polkadot.json \
              -v $(pwd)/my-node-data:/data \
              parity/polkadot-parachain:stable2603 \
              --name=PeopleChainRPC \
              --base-path=/data \
              --chain=/people-polkadot.json \
              --prometheus-external \
              --prometheus-port 9615 \
              --unsafe-rpc-external \
              --rpc-port=9944 \
              --rpc-cors=all \
              --rpc-methods=safe \
              --rpc-max-connections=1000 \
              --state-pruning=1000 \
              --blocks-pruning=256 \
              -- \
              --base-path=/data \
              --chain=polkadot \
              --state-pruning=256 \
              --blocks-pruning=256 \
              --rpc-port=0
            ```

        !!! note
            The `parity/polkadot-parachain` image works for system parachains and parachains built with standard Cumulus templates. For parachains with custom runtimes, check the parachain's documentation for their specific Docker image or binary.

        Refer to the [Port Mappings](#port-mappings) and [Node Configuration Parameters](#node-configuration-parameters) sections for details on the command's configurations.

=== "systemd"

    1. Download the `polkadot-parachain` binary from the latest stable [Polkadot SDK release](https://github.com/paritytech/polkadot-sdk/releases):

        ```bash
        # Download the latest stable release (check releases page for current version)
        wget https://github.com/paritytech/polkadot-sdk/releases/download/polkadot-stable2603/polkadot-parachain

        # Make it executable and move to system path
        chmod +x polkadot-parachain
        sudo mv polkadot-parachain /usr/local/bin/

        # Verify installation
        polkadot-parachain --version
        ```

    2. Download your parachain's chain specification as described in [Obtain the Chain Specification](#obtain-the-chain-specification).

    3. Create user and directory structures:

        ```bash
        # Create a dedicated user
        sudo useradd -r -s /bin/bash polkadot

        # Create data directory
        sudo mkdir -p /var/lib/people-chain-rpc

        # Copy the chain spec to the directory
        sudo cp people-polkadot.json /var/lib/people-chain-rpc/

        # Set permissions
        sudo chown -R polkadot:polkadot /var/lib/people-chain-rpc
        ```

    4. Create a systemd service file for the Polkadot SDK RPC node:

        ```bash
        sudo nano /etc/systemd/system/people-chain-rpc.service
        ```

    5. Open the new service file and add the configuration for either an archive (complete history) or pruned (recent state) node:

        === "Archive"

            ```ini
            [Unit]
            Description=People Chain RPC Node
            After=network.target

            [Service]
            Type=simple
            User=polkadot
            Group=polkadot
            WorkingDirectory=/var/lib/people-chain-rpc

            ExecStart=/usr/local/bin/polkadot-parachain \
              --name=PeopleChainRPC \
              --chain=/var/lib/people-chain-rpc/people-polkadot.json \
              --base-path=/var/lib/people-chain-rpc \
              --port=30333 \
              --rpc-port=9944 \
              --rpc-external \
              --rpc-cors=all \
              --rpc-methods=safe \
              --rpc-max-connections=1000 \
              --prometheus-port=9615 \
              --prometheus-external \
              --state-pruning=archive \
              --blocks-pruning=archive \
              -- \
              --chain=polkadot \
              --base-path=/var/lib/people-chain-rpc \
              --port=30334 \
              --state-pruning=256 \
              --blocks-pruning=256 \
              --rpc-port=0

            Restart=always
            RestartSec=10
            LimitNOFILE=65536

            [Install]
            WantedBy=multi-user.target
            ```

        === "Pruned"

            ```ini
            [Unit]
            Description=People Chain RPC Node
            After=network.target

            [Service]
            Type=simple
            User=polkadot
            Group=polkadot
            WorkingDirectory=/var/lib/people-chain-rpc

            ExecStart=/usr/local/bin/polkadot-parachain \
              --name=PeopleChainRPC \
              --chain=/var/lib/people-chain-rpc/people-polkadot.json \
              --base-path=/var/lib/people-chain-rpc \
              --port=30333 \
              --rpc-port=9944 \
              --rpc-external \
              --rpc-cors=all \
              --rpc-methods=safe \
              --rpc-max-connections=1000 \
              --prometheus-port=9615 \
              --prometheus-external \
              --state-pruning=1000 \
              --blocks-pruning=256 \
              -- \
              --chain=polkadot \
              --base-path=/var/lib/people-chain-rpc \
              --port=30334 \
              --state-pruning=256 \
              --blocks-pruning=256 \
              --rpc-port=0

            Restart=always
            RestartSec=10
            LimitNOFILE=65536

            [Install]
            WantedBy=multi-user.target
            ```

        Refer to the [Port Mappings](#port-mappings) and [Node Configuration Parameters](#node-configuration-parameters) sections for details on the command's configurations.

    6. Start the service:

        ```bash
        # Reload systemd
        sudo systemctl daemon-reload

        # Enable service to start on boot
        sudo systemctl enable people-chain-rpc

        # Start the Polkadot SDK node:
        sudo systemctl start people-chain-rpc
        ```


Port Mappings

### Port Mappings

- **`9944`**: Polkadot SDK RPC endpoint (WebSocket/HTTP)
- **`9933`**: Polkadot SDK HTTP RPC endpoint
- **`9615`**: Prometheus metrics endpoint
- **`30333/30334`**: P2P networking ports


Node Configuration Parameters

### Node Configuration Parameters

- **`--unsafe-rpc-external`**: Enables external RPC access. **This command should only be used in development or properly secured environments**. For production, use a reverse proxy with authentication.
- **`--rpc-cors=all`**: Allows all origins for CORS.
- **`--rpc-methods=safe`**: Only allows safe RPC methods.
- **`--state-pruning`**: Archive keeps complete state history, pruned keeps last specified number of blocks.
- **`--blocks-pruning`**: Archive keeps all blocks, pruned keeps last specified number of finalized blocks.
- **`--prometheus-external`**: Exposes metrics externally.


Monitor Node Synchronization

## Monitor Node Synchronization

Monitor the node synchronization status:

```bash
curl -H "Content-Type: application/json" \
-d '{"id":1, "jsonrpc":"2.0", "method": "system_syncState", "params":[]}' \
http://localhost:9944
```

When synchronization is complete, `currentBlock` will be equal to `highestBlock`:

  curl -H "Content-Type: application/json" \
  -d '{"id":1, "jsonrpc":"2.0", "method": "system_syncState", "params":[]}' \
  http://localhost:9944

{
  "jsonrpc":"2.0",
  "id":1,
  "result":{
    "startingBlock":0,
    "currentBlock":3394816,
    "highestBlock":3394816
  }
}

!!! tip
    You can use the `system_health` command to verify your node is running properly.

    ```bash
    curl -H "Content-Type: application/json" \
    -d '{"id":1, "jsonrpc":"2.0", "method": "system_health", "params":[]}' \
    http://localhost:9944
    ```


Commands for Managing Your Node

## Commands for Managing Your Node

Use the following commands to manage your node:

=== "Docker"

    - **View node logs**:

        ```bash
        docker logs -f people-chain-rpc
        ```

    - **Stop container**:

        ```bash
        docker stop people-chain-rpc
        ```

    - **Start container**:

        ```bash
        docker start people-chain-rpc
        ```

    - **Remove container**:

        ```bash
        docker rm people-chain-rpc
        ```

=== "systemd"

    - **Check status**:

        ```bash
        sudo systemctl status people-chain-rpc
        ```

    - **View node logs**:

        ```bash
        sudo journalctl -u people-chain-rpc -f
        ```

    - **Stop service**:

        ```bash
        sudo systemctl stop people-chain-rpc
        ```

    - **Enable service**:

        ```bash
        sudo systemctl enable people-chain-rpc
        ```

    - **Start service**:

        ```bash
        sudo systemctl start people-chain-rpc
        ```


Conclusion

## Conclusion

Running a parachain RPC node provides critical infrastructure for accessing Polkadot network services. By following this guide, you have set up a production-ready RPC node that:

- Provides reliable access to parachain functionality for applications and users.
- Supports flexible deployment with both Docker and systemd options.
- Implements comprehensive monitoring, security, and maintenance practices.
- Can be adapted for any parachain by substituting the appropriate chain specification.

Whether you're running a node for system parachains (People Chain, Bridge Hub, Coretime Chain) or other parachains in the ecosystem, regular maintenance and monitoring will ensure your RPC node continues to provide reliable service. Stay updated with the latest releases and best practices to keep your infrastructure secure and performant.


Introduction

## Introduction

[Polkadot Hub](/reference/polkadot-hub/) is the gateway to the Polkadot network, providing access to core services such as asset management, governance, and cross-chain messaging. Running your own RPC node gives developers and applications direct access to these services while also supporting infrastructure tasks like block indexing and SDK tool compatibility.

Through the Polkadot SDK node RPC (WebSocket port 9944, HTTP port 9933), your node serves as the bridge between the network and applications. Additionally, you can run the Ethereum RPC adapter to enable Ethereum JSON-RPC compatibility (port 8545) for seamless integration with Ethereum tools and wallets. This page guides you through setting up a node from scratch, including hardware requirements and deployment options using Docker or systemd.


Hardware Requirements

### Hardware Requirements

RPC nodes serving production traffic require robust hardware. The following should be considered the minimum standard to effectively operate an RPC node:

- **CPU**: 8+ cores; 16+ cores for high traffic
- **Memory**: 64 GB RAM minimum; 128 GB recommended for high traffic
- **Storage**:
    - **Archive node (complete history)**: ~1.2 TB NVMe SSD total (~392 GB for Asset Hub archive + ~822 GB for relay chain pruned snapshot)
    - **Pruned node (recent state)**: ~200 GB NVMe SSD total (with pruning enabled for both parachain and relay chain)
    - Fast disk I/O is critical for query performance
- **Network**:
    - Public IP address
    - Stable internet connection with sufficient bandwidth
    - 1 Gbps connection for high traffic scenarios
    - Consider DDoS protection and rate limiting for production deployments
    - Open ports:
        - **30333**: Parachain P2P
        - **30334**: Relay chain P2P
        - **9944**: Polkadot SDK WebSocket RPC
        - **9933**: Polkadot SDK HTTP RPC
        - **8545**: Ethereum JSON-RPC (if running `eth-rpc` adapter)

!!! note
    For development or low-traffic scenarios, you can reduce these requirements proportionally. Consider using a reverse proxy ([nginx](https://nginx.org/), [Caddy](https://caddyserver.com/)) for production deployments.


Software Requirements


Spin Up a Node

## Spin Up a Node

This guide provides two options for deployment:

- **Docker**: Best for simpler set up and maintenance
- **systemd**: Best for production environments requiring more control

Select the best option for your project, then use the steps in the following tabs to complete set up.

=== "Docker"

    1. Download the official Polkadot Hub (formerly known as Asset Hub) chain specification file:

        ```bash
        curl -L https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/cumulus/parachains/chain-specs/asset-hub-polkadot.json -o asset-hub-polkadot.json
        ```

    2. (Optional but recommended) Download pre-synced snapshots from the [Snapshot Provider](https://snapshots.polkadot.io/) to cut initial sync time from days to hours:

        1. Create new directories:

            ```bash
            mkdir -p my-node-data/chains/asset-hub-polkadot/db
            mkdir -p my-node-data/chains/polkadot/db
            ```

        2. Download and save the archive Asset Hub snapshot:

            ```bash
            # Check https://snapshots.polkadot.io/ for the latest snapshot URL
            export SNAPSHOT_URL_ASSET_HUB="https://snapshots.polkadot.io/polkadot-asset-hub-rocksdb-archive/INSERT_LATEST"

            rclone copyurl $SNAPSHOT_URL_ASSET_HUB/files.txt files.txt
            rclone copy --progress --transfers 20 \
              --http-url $SNAPSHOT_URL_ASSET_HUB \
              --no-traverse --http-no-head --disable-http2 \
              --inplace --no-gzip-encoding --size-only \
              --retries 6 --retries-sleep 10s \
              --files-from files.txt :http: my-node-data/chains/asset-hub-polkadot/db/

            rm files.txt
            ```

            ??? interface "rclone parameters"

                - **`--transfers 20`**: Uses 20 parallel transfers for faster download
                - **`--retries 6`**: Automatically retries failed transfers up to 6 times
                - **`--retries-sleep 10s`**: Waits 10 seconds between retry attempts
                - **`--size-only`**: Only transfers if sizes differ (prevents unnecessary re-downloads)

        3. Repeat the process with the pruned relay chain snapshot:

            ```bash
            # Check https://snapshots.polkadot.io/ for the latest snapshot URL
            export SNAPSHOT_URL_RELAY="https://snapshots.polkadot.io/polkadot-rocksdb-prune/INSERT_LATEST"

            rclone copyurl $SNAPSHOT_URL_RELAY/files.txt files.txt
            rclone copy --progress --transfers 20 \
              --http-url $SNAPSHOT_URL_RELAY \
              --no-traverse --http-no-head --disable-http2 \
              --inplace --no-gzip-encoding --size-only \
              --retries 6 --retries-sleep 10s \
              --files-from files.txt :http: my-node-data/chains/polkadot/db/

            rm files.txt
            ```

    3. Launch your Polkadot Hub node using the official [Parity Docker image](https://hub.docker.com/r/parity/polkadot-parachain):

        === "Archive"

            ```bash
            docker run -d --name polkadot-hub-rpc --restart unless-stopped \
              -p 9944:9944 \
              -p 9933:9933 \
              -p 9615:9615 \
              -p 30334:30334 \
              -p 30333:30333 \
              -v $(pwd)/asset-hub-polkadot.json:/asset-hub-polkadot.json \
              -v $(pwd)/my-node-data:/data \
              parity/polkadot-parachain:stable2603 \
              --name=PolkadotHubRPC \
              --base-path=/data \
              --chain=/asset-hub-polkadot.json \
              --prometheus-external \
              --prometheus-port 9615 \
              --unsafe-rpc-external \
              --rpc-port=9944 \
              --rpc-cors=all \
              --rpc-methods=safe \
              --rpc-max-connections=1000 \
              --state-pruning=archive \
              --blocks-pruning=archive \
              -- \
              --base-path=/data \
              --chain=polkadot \
              --state-pruning=256 \
              --blocks-pruning=256 \
              --rpc-port=0
            ```

        === "Pruned"

            ```bash
            docker run -d --name polkadot-hub-rpc --restart unless-stopped \
              -p 9944:9944 \
              -p 9933:9933 \
              -p 9615:9615 \
              -p 30334:30334 \
              -p 30333:30333 \
              -v $(pwd)/asset-hub-polkadot.json:/asset-hub-polkadot.json \
              -v $(pwd)/my-node-data:/data \
              parity/polkadot-parachain:stable2603 \
              --name=PolkadotHubRPC \
              --base-path=/data \
              --chain=/asset-hub-polkadot.json \
              --prometheus-external \
              --prometheus-port 9615 \
              --unsafe-rpc-external \
              --rpc-port=9944 \
              --rpc-cors=all \
              --rpc-methods=safe \
              --rpc-max-connections=1000 \
              --state-pruning=1000 \
              --blocks-pruning=256 \
              -- \
              --base-path=/data \
              --chain=polkadot \
              --state-pruning=256 \
              --blocks-pruning=256 \
              --rpc-port=0
            ```

        Refer to the [Port Mappings](#port-mappings) and [Node Configuration Arguments](#node-configuration-arguments) sections for details on the command's configurations.

=== "systemd"

    1. Download the `polkadot-parachain` binary from the latest stable [Polkadot SDK release](https://github.com/paritytech/polkadot-sdk/releases):

        ```bash
        # Download the latest stable release (check releases page for current version)
        wget https://github.com/paritytech/polkadot-sdk/releases/download/polkadot-stable2603/polkadot-parachain

        # Make it executable and move to system path
        chmod +x polkadot-parachain
        sudo mv polkadot-parachain /usr/local/bin/

        # Verify installation
        polkadot-parachain --version
        ```

    2. Download the Polkadot Hub chain specification:

        ```bash
        curl -L https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/cumulus/parachains/chain-specs/asset-hub-polkadot.json -o asset-hub-polkadot.json
        ```

    3. Create user and directory structures:

        ```bash
        # Create a dedicated user
        sudo useradd -r -s /bin/bash polkadot

        # Create data directory
        sudo mkdir -p /var/lib/polkadot-hub-rpc

        # Copy the chain spec to the directory
        sudo cp asset-hub-polkadot.json /var/lib/polkadot-hub-rpc/

        # Set permissions
        sudo chown -R polkadot:polkadot /var/lib/polkadot-hub-rpc
        ```

    4. Create a systemd service file for the Polkadot SDK RPC node:

        ```bash
        sudo nano /etc/systemd/system/polkadot-hub-rpc.service
        ```

    5. Open the new service file and add the configuration for either an archive (complete history) or pruned (recent state) node:

        === "Archive"

            ```ini
            [Unit]
            Description=Polkadot Hub RPC Node
            After=network.target

            [Service]
            Type=simple
            User=polkadot
            Group=polkadot
            WorkingDirectory=/var/lib/polkadot-hub-rpc

            ExecStart=/usr/local/bin/polkadot-parachain \
              --name=PolkadotHubRPC \
              --chain=/var/lib/polkadot-hub-rpc/asset-hub-polkadot.json \
              --base-path=/var/lib/polkadot-hub-rpc \
              --port=30333 \
              --rpc-port=9944 \
              --rpc-external \
              --rpc-cors=all \
              --rpc-methods=safe \
              --rpc-max-connections=1000 \
              --prometheus-port=9615 \
              --prometheus-external \
              --state-pruning=archive \
              --blocks-pruning=archive \
              -- \
              --chain=polkadot \
              --base-path=/var/lib/polkadot-hub-rpc \
              --port=30334 \
              --state-pruning=256 \
              --blocks-pruning=256 \
              --rpc-port=0

            Restart=always
            RestartSec=10
            LimitNOFILE=65536

            [Install]
            WantedBy=multi-user.target
            ```

        === "Pruned Node"

            ```ini
            [Unit]
            Description=Polkadot Hub RPC Node
            After=network.target

            [Service]
            Type=simple
            User=polkadot
            Group=polkadot
            WorkingDirectory=/var/lib/polkadot-hub-rpc

            ExecStart=/usr/local/bin/polkadot-parachain \
              --name=PolkadotHubRPC \
              --chain=/var/lib/polkadot-hub-rpc/asset-hub-polkadot.json \
              --base-path=/var/lib/polkadot-hub-rpc \
              --port=30333 \
              --rpc-port=9944 \
              --rpc-external \
              --rpc-cors=all \
              --rpc-methods=safe \
              --rpc-max-connections=1000 \
              --prometheus-port=9615 \
              --prometheus-external \
              --state-pruning=1000 \
              --blocks-pruning=256 \
              -- \
              --chain=polkadot \
              --base-path=/var/lib/polkadot-hub-rpc \
              --port=30334 \
              --state-pruning=256 \
              --blocks-pruning=256 \
              --rpc-port=0

            Restart=always
            RestartSec=10
            LimitNOFILE=65536

            [Install]
            WantedBy=multi-user.target
            ```

        Refer to the [Port Mappings](#port-mappings) and [Node Configuration Arguments](#node-configuration-arguments) sections for details on the command's configurations.

    6. Start the service:

        ```bash
        # Reload systemd
        sudo systemctl daemon-reload

        # Enable service to start on boot
        sudo systemctl enable polkadot-hub-rpc

        # Start the Polkadot SDK node:
        sudo systemctl start polkadot-hub-rpc
        ```


Port Mappings


Node Configuration Arguments

### Node Configuration Arguments

- **`--unsafe-rpc-external`**: Enables external RPC access. **This command should only be used in development or properly secured environments**. For production, use a reverse proxy with authentication.
- **`--rpc-cors=all`**: Allows all origins for CORS.
- **`--rpc-methods=safe`**: Only allows safe RPC methods.
- **`--state-pruning`**: Archive keeps complete state history, pruned keeps last specified number of blocks.
- **`--blocks-pruning`**: Archive keeps all blocks, pruned keeps last specified number of finalized blocks.
- **`--prometheus-external`**: Exposes metrics externally.


Monitor Node Synchronization


Commands for Managing Your Node

## Commands for Managing Your Node

Use the following commands to manage your node:

=== "Docker"

    - **View node logs**:

        ```bash
        docker logs -f polkadot-hub-rpc
        ```

    - **Stop container**:

        ```bash
        docker stop polkadot-hub-rpc
        ```

    - **Start container**:

        ```bash
        docker start polkadot-hub-rpc
        ```

    - **Remove container**:

        ```bash
        docker rm polkadot-hub-rpc
        ```

=== "systemd"

    - **Check status**:

        ```bash
        sudo systemctl status polkadot-hub-rpc
        ```

    - **View node logs**:

        ```bash
        sudo journalctl -u polkadot-hub-rpc -f
        ```

    - **Stop service**:

        ```bash
        sudo systemctl stop polkadot-hub-rpc
        ```

    - **Enable service**:

        ```bash
        sudo systemctl enable polkadot-hub-rpc
        ```

    - **Start service**:

        ```bash
        sudo systemctl start polkadot-hub-rpc
        ```


Ethereum RPC Compatibility

## Ethereum RPC Compatibility

Polkadot Hub supports Ethereum RPC compatibility through the `eth-rpc` adapter, which is part of [pallet-revive](https://paritytech.github.io/polkadot-sdk/master/pallet_revive_eth_rpc/index.html). This adapter translates Ethereum JSON-RPC calls into Polkadot SDK-compatible requests, enabling seamless integration with Ethereum tools like [MetaMask](https://metamask.io/), [Hardhat](https://hardhat.org/), and [Ethers.js](https://docs.ethers.org/v6/).


Prerequisites

### Prerequisites

Before starting the Ethereum RPC adapter:

- **Node synchronization** - your Polkadot Hub node must be **fully synchronized**. The eth-rpc adapter requires access to current chain state and will fail to start if the node is still syncing
- **Archive node recommended** - for full Ethereum RPC compatibility, running an **archive node** (`--state-pruning=archive`) is recommended. The eth-rpc adapter may fail to query historical state on pruned nodes
- **RPC accessibility** - the Polkadot SDK-based RPC endpoint must be accessible (default: `ws://127.0.0.1:9944`)