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

# Initia Registry

For a rollup to be supported by the core Initia apps such as Initia Wallet,
Initia Scan, and Initia App, it must be registered on the
[Initia Registry](https://github.com/initia-labs/initia-registry). This is a
public GitHub repository that contains the metadata for all rollups that are
currently live on the various Initia networks.

## Adding a Rollup to the Registry

To add a rollup to the registry, follow these steps:

### Fork the Initia Registry Repository

To make changes to the registry, you will need to fork the
[Initia Registry](https://github.com/initia-labs/initia-registry) repository.
This will create a copy of the repository in your own GitHub account.

### Add the Rollup to the Registry

Once you have forked the repository, you can add the rollup to the registry by
following these steps:

1. Add a new folder with your rollup's name in the `testnets` or `mainnets`
   folder, depending on whether your rollup is currently live on the testnet or
   mainnet.
2. Add a `chain.json` file to the folder. This file will contain the metadata
   for your rollup to be used by the apps.

<Accordion title="Example Chain Schema and Description" icon="link">
  ```json theme={null}
  {
    "$schema": "../../chain.schema.json",
    "chain_name": "move",
    "pretty_name": "Move",
    "chain_id": "move-1",
    "bech32_prefix": "init",
    "network_type": "testnet",
    "codebase": {
      "git_repo": "https://github.com/initia-labs/minimove",
      "recommended_version": "v1.0.7",
      "binaries": {
        "linux/amd64": "https://github.com/initia-labs/minimove/releases/download/v1.0.7/minimove_v1.0.7_Linux_x86_64.tar.gz",
        "linux/arm64": "https://github.com/initia-labs/minimove/releases/download/v1.0.7/minimove_v1.0.7_Linux_aarch64.tar.gz",
        "darwin/amd64": "https://github.com/initia-labs/minimove/releases/download/v1.0.7/minimove_v1.0.7_Darwin_x86_64.tar.gz",
        "darwin/arm64": "https://github.com/initia-labs/minimove/releases/download/v1.0.7/minimove_v1.0.7_Darwin_aarch64.tar.gz"
      },
      "genesis": {
        "genesis_url": "https://rpc-move-1.anvil.asia-southeast.initia.xyz/genesis"
      }
    },
    "apis": {
      "rpc": [
        {
          "address": "https://rpc-move-1.anvil.asia-southeast.initia.xyz"
        }
      ],
      "rest": [
        {
          "address": "https://rest-move-1.anvil.asia-southeast.initia.xyz"
        }
      ],
      "grpc": [
        {
          "address": "grpc-move-1.anvil.asia-southeast.initia.xyz:443"
        }
      ],
      "indexer": [
        {
          "address": "https://rollytics-api-move-1.anvil.asia-southeast.initia.xyz"
        }
      ]
    },
    "explorers": [
      {
        "kind": "initia scan",
        "url": "https://scan.testnet.initia.xyz/move-1",
        "tx_page": "https://scan.testnet.initia.xyz/move-1/txs/${txHash}",
        "account_page": "https://scan.testnet.initia.xyz/move-1/accounts/${accountAddress}"
      }
    ],
    "key_algos": ["secp256k1"],
    "slip44": 118,
    "fees": {
      "fee_tokens": [
        {
          "denom": "l2/07b129ceb9c4b0bdef7db171ce1e22f90d34bc930058b23e21adf8cc938d8145",
          "fixed_min_gas_price": 0.015
        }
      ]
    },
    "images": [
      {
        "png": "https://raw.githubusercontent.com/initia-labs/initia-registry/main/images/minimove.png"
      }
    ],
    "logo_URIs": {
      "png": "https://raw.githubusercontent.com/initia-labs/initia-registry/main/images/minimove.png"
    },
    "metadata": {
      "op_bridge_id": "1458",
      "op_denoms": ["uinit"],
      "executor_uri": "https://opinit-api-move-1.anvil.asia-southeast.initia.xyz",
      "ibc_channels": [
        {
          "chain_id": "initiation-2",
          "port_id": "nft-transfer",
          "channel_id": "channel-1",
          "version": "ics721-1"
        },
        {
          "chain_id": "initiation-2",
          "port_id": "transfer",
          "channel_id": "channel-0",
          "version": "ics20-1"
        }
      ],
      "assetlist": "https://raw.githubusercontent.com/initia-labs/initia-registry/main/testnets/move/assetlist.json",
      "minitia": {
        "type": "minimove",
        "version": "v1.0.7"
      }
    }
  }
  ```

  #### Description

  **General Information**

  | Field           | Description                                                                                                   | Optional |
  | --------------- | ------------------------------------------------------------------------------------------------------------- | -------- |
  | `$schema`       | The schema definition file. (should always be `../../chain.schema.json`)                                      | No       |
  | `chain_name`    | The name of the rollup.                                                                                       | No       |
  | `chain_id`      | The chain ID of the rollup.                                                                                   | No       |
  | `website`       | The website of the rollup.                                                                                    | No       |
  | `pretty_name`   | A human-readable name for your rollup.                                                                        | No       |
  | `status`        | The current status of the rollup (e.g., live).                                                                | No       |
  | `network_type`  | The type of network (one of `mainnet`, `testnet`, `devnet`).                                                  | No       |
  | `bech32_prefix` | The Bech32 prefix used for addresses on the blockchain.                                                       | No       |
  | `daemon_name`   | The name of the daemon process for the blockchain (e.g., minitiad).                                           | No       |
  | `node_home`     | The default home directory for the blockchain node.                                                           | No       |
  | `key_algos`     | The cryptographic algorithms supported for keys.                                                              | No       |
  | `slip44`        | The [SLIP-0044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md) identifier for the blockchain. | No       |
  | `description`   | A brief description of the rollup.                                                                            | No       |

  **Fees**

  | Field        | Description                                                         | Optional |
  | ------------ | ------------------------------------------------------------------- | -------- |
  | `fees`       | Details about the fee and fee tokens on the rollup.                 | No       |
  | `fee_tokens` | Tokens used for fees, including their denominations and gas prices. | No       |

  **Staking**

  These fields should be empty for all rollups.

  | Field            | Description                              | Optional |
  | ---------------- | ---------------------------------------- | -------- |
  | `staking`        | Information about staking on the rollup. | No       |
  | `staking_tokens` | Tokens used for staking.                 | No       |

  **Codebase**

  | Field                 | Description                                                                                                      | Optional |
  | --------------------- | ---------------------------------------------------------------------------------------------------------------- | -------- |
  | `codebase`            | Information about the blockchain's codebase.                                                                     | No       |
  | `git_repo`            | The URL of the Git repository for the rollup.                                                                    | No       |
  | `recommended_version` | The recommended version of the rollup software. This should in most cases be the latest version of the software. | No       |
  | `compatible_versions` | Versions of the rollup software that are compatible.                                                             | No       |
  | `binaries`            | URLs for downloading binary files for different platforms.                                                       | No       |
  | `genesis`             | Information about the genesis block of the rollup.                                                               | No       |
  | `genesis_url`         | The URL to download the rollup genesis file.                                                                     | No       |
  | `versions`            | List of versions of the rollup software.                                                                         | No       |

  **Peers**

  | Field              | Description                                  | Optional |
  | ------------------ | -------------------------------------------- | -------- |
  | `peers`            | Information about network peers.             | No       |
  | `seeds`            | The list of seed nodes for the rollup.       | No       |
  | `persistent_peers` | The list of persistent peers for the rollup. | No       |

  **APIs**

  | Field  | Description                                               | Optional |
  | ------ | --------------------------------------------------------- | -------- |
  | `apis` | Information about the different endpoints for the rollup. | No       |
  | `rpc`  | RPC endpoints and their providers.                        | No       |
  | `rest` | REST endpoints and their providers.                       | No       |
  | `grpc` | gRPC endpoints and their providers.                       | No       |

  **Explorers**

  | Field          | Description                                     | Optional |
  | -------------- | ----------------------------------------------- | -------- |
  | `explorers`    | Blockchain explorers available for the network. | No       |
  | `kind`         | The type of explorer.                           | No       |
  | `url`          | The URL of the explorer.                        | No       |
  | `tx_page`      | The URL template for transaction pages.         | No       |
  | `account_page` | The URL template for account pages.             | No       |

  **Images**

  | Field       | Description                                | Optional |
  | ----------- | ------------------------------------------ | -------- |
  | `images`    | URLs for images related to the blockchain. | No       |
  | `png`       | URL for the PNG image.                     | No       |
  | `svg`       | URL for the SVG image.                     | No       |
  | `logo_URIs` | URLs for the blockchain logo.              | No       |

  **Metadata**

  | Field          | Description                                                      | Optional |
  | -------------- | ---------------------------------------------------------------- | -------- |
  | `metadata`     | Additional metadata about the blockchain.                        | No       |
  | `op_bridge_id` | The bridge ID for operations.                                    | Yes      |
  | `op_denoms`    | Denominations used by the OP Bridge.                             | Yes      |
  | `executor_uri` | The URI for the executor service.                                | Yes      |
  | `ibc_channels` | Information about IBC channels.                                  | Yes      |
  | `chain_id`     | The chain ID for the IBC channel.                                | No       |
  | `port_id`      | The port ID for the IBC channel.                                 | No       |
  | `channel_id`   | The channel ID for the IBC channel.                              | No       |
  | `version`      | The version of the IBC protocol used.                            | No       |
  | `assetlist`    | URL for the asset list JSON file.                                | Yes      |
  | `minitia`      | Specific metadata for the rollup.                                | No       |
  | `type`         | The type of chain (one of `minimove`, `minievm`, or `miniwasm`). | No       |
  | `version`      | The version of the rollup.                                       | No       |
</Accordion>

3. Create an `assetlist.json` file in the folder. This file will contain the
   metadata for the assets on your rollup to be used by the apps.

<Accordion title="Example Assetlist Schema and Description" icon="coin-front">
  ```json theme={null}
  {
    "$schema": "../../assetlist.schema.json",
    "chain_name": "move",
    "assets": [
      {
        "description": "The native token of Initia",
        "denom_units": [
          {
            "denom": "l2/07b129ceb9c4b0bdef7db171ce1e22f90d34bc930058b23e21adf8cc938d8145",
            "exponent": 0
          },
          {
            "denom": "INIT",
            "exponent": 6
          }
        ],
        "base": "l2/07b129ceb9c4b0bdef7db171ce1e22f90d34bc930058b23e21adf8cc938d8145",
        "display": "INIT",
        "traces": [
          {
            "type": "op",
            "counterparty": {
              "base_denom": "uinit",
              "chain_name": "initia"
            },
            "chain": {
              "bridge_id": "1"
            }
          }
        ],
        "name": "Initia Native Token",
        "symbol": "INIT",
        "coingecko_id": "",
        "images": [
          {
            "png": "https://raw.githubusercontent.com/initia-labs/initia-registry/main/testnets/minimove/images/INIT.png",
            "svg": "https://raw.githubusercontent.com/initia-labs/initia-registry/main/testnets/minimove/images/INIT.svg"
          }
        ],
        "logo_URIs": {
          "png": "https://raw.githubusercontent.com/initia-labs/initia-registry/main/testnets/minimove/images/INIT.png",
          "svg": "https://raw.githubusercontent.com/initia-labs/initia-registry/main/testnets/minimove/images/INIT.svg"
        }
      }
    ]
  }
  ```

  **General Information**

  | Field         | Description                   | Optional |
  | ------------- | ----------------------------- | -------- |
  | name          | The name of the token         | No       |
  | symbol        | The symbol of the token       | No       |
  | description   | The description of the token  | No       |
  | coingecko\_id | The CoinGecko ID of the token | Yes      |

  **Denomination Units**

  | Field                 | Description                                        | Optional |
  | --------------------- | -------------------------------------------------- | -------- |
  | denom\_units          | List of denomination units                         | No       |
  | denom\_units.denom    | The denomination identifier (e.g. "uinit", "INIT") | No       |
  | denom\_units.exponent | The exponent of the denomination (e.g. 0, 6)       | No       |

  **Base and Display**

  | Field   | Description                                             | Optional |
  | ------- | ------------------------------------------------------- | -------- |
  | base    | The base denomination of the token (e.g. uinit, l2/...) | No       |
  | display | The display denomination identifier (e.g. INIT)         | No       |

  **Traces**

  | Field                           | Description                                     | Optional |
  | ------------------------------- | ----------------------------------------------- | -------- |
  | traces                          | List of trace information for the token         | No       |
  | traces.type                     | The type of trace (e.g., "op", "ibc")           | No       |
  | traces.counterparty             | Information about the counterparty chain        | No       |
  | traces.counterparty.base\_denom | The base denomination on the counterparty chain | No       |
  | traces.counterparty.chain\_name | The name of the counterparty chain              | No       |
  | traces.counterparty.channel\_id | The channel ID on the counterparty chain        | Yes      |
  | traces.chain                    | Information about the current chain             | No       |
  | traces.chain.bridge\_id         | The bridge ID on the current chain              | Yes      |
  | traces.chain.channel\_id        | The channel ID on the current chain             | Yes      |
  | traces.chain.path               | The path on the current chain                   | Yes      |

  **Images**

  | Field      | Description                      | Optional |
  | ---------- | -------------------------------- | -------- |
  | images     | List of image URIs for the token | No       |
  | images.png | The PNG image URI for the token  | No       |
  | images.svg | The SVG image URI for the token  | No       |

  **Logo URIs**

  | Field          | Description                               | Optional |
  | -------------- | ----------------------------------------- | -------- |
  | logo\_URIs     | Object containing logo URIs for the token | No       |
  | logo\_URIs.png | The PNG logo URI for the token            | No       |
  | logo\_URIs.svg | The SVG logo URI for the token            | No       |
</Accordion>

<Accordion title="How to Derive a Bridged Token Denom" icon="coin-front">
  For tokens bridged from L1, the denom can vary depending on the type of bridge
  used. In order for token bridging to work correctly, you must add the
  appropriate denom to your assetlist.

  We have two scenarios for calculating the denom:

  * OP Denom: The denom used in the OP Bridge
  * IBC Denom: The denom used in the IBC Bridge

  **OP Denom**

  ```typescript denom.ts theme={null}
  import { RESTClient } from '@initia/initia.js'

  /**
   *
   * Queries the Initia REST API to find the L2 (Layer 2) denomination
   * corresponding to a given L1 (Layer 1) denomination, for a specific bridge ID.
   *
   * @param {string} uri - The REST endpoint for the Initia network (e.g., "https://rest.testnet.initia.xyz").
   * @param {number} bridge_id - The bridge ID (e.g., 1).
   * @param {string} l1_denom - The L1 denomination (e.g., "uinit").
   * @returns {Promise<string>} - The corresponding L2 denomination (e.g., "l2/...").
   */
  export async function opDenomByL1Denom(
    uri: string,
    bridge_id: number,
    l1_denom: string,
  ): Promise<string> {
    const restClient = new RESTClient(uri)
    const tokenPair = await restClient.ophost.tokenPairByL1Denom(
      bridge_id,
      l1_denom,
    )
    return tokenPair.l2_denom
  }

  /**
   *
   * Queries the Initia REST API to find the L1 (Layer 1) denomination
   * corresponding to a given L2 (Layer 2) denomination, for a specific bridge ID.
   *
   * @param {string} uri - The REST endpoint for the Initia network (e.g., "https://rest.testnet.initia.xyz").
   * @param {number} bridge_id - The bridge ID (e.g., 1).
   * @param {string} l2_denom - The L2 denomination (e.g., "l2/xyz...").
   * @returns {Promise<string>} - The corresponding L1 denomination (e.g., "uinit").
   */
  export async function opDenomByL2Denom(
    uri: string,
    bridge_id: number,
    l2_denom: string,
  ): Promise<string> {
    const restClient = new RESTClient(uri)
    const tokenPair = await restClient.ophost.tokenPairByL2Denom(
      bridge_id,
      l2_denom,
    )
    return tokenPair.l1_denom
  }

  async function main() {
    // Example usage of opDenomByL1Denom and opDenomByL2Denom
    const uri = 'https://rest.testnet.initia.xyz'
    const bridge_id = 1

    const l1_denom = 'uinit'
    const l2_denom =
      'l2/07b129ceb9c4b0bdef7db171ce1e22f90d34bc930058b23e21adf8cc938d8145'

    const l2_denom_for_l1_denom = await opDenomByL1Denom(uri, bridge_id, l1_denom)
    console.log(`L2 denom for L1 denom "${l1_denom}":`, l2_denom_for_l1_denom)

    const l1_denom_for_l2_denom = await opDenomByL2Denom(uri, bridge_id, l2_denom)
    console.log(`L1 denom for L2 denom "${l2_denom}":`, l1_denom_for_l2_denom)
  }

  main().catch((error) => {
    console.error('Error in main:', error)
  })
  ```

  **IBC Denom**

  ```typescript denom.ts theme={null}
  import { RESTClient, sha256 } from '@initia/initia.js'

  interface DenomTrace {
    denom_trace: {
      path: string
      base_denom: string
    }
  }

  /**
   *
   * Takes a full trace string (e.g., "transfer/channel-0/uinit"), computes its SHA-256 hash,
   * and returns it in uppercase as "ibc/<HASH>".
   *
   * @param {string} fullTrace - For example, "transfer/channel-0/uinit".
   * @returns {string} - For example, "ibc/2A3B4C...".
   */
  function makeIBCHash(fullTrace: string): string {
    const shaSum = sha256(Buffer.from(fullTrace))
    const hash = Buffer.from(shaSum).toString('hex').toUpperCase()
    return `ibc/${hash}`
  }

  /**
   *
   * Retrieves the original "transfer/..." full trace (e.g., "transfer/channel-0/uinit")
   * from an IBC denom that starts with "ibc/...". It queries the IBC module's
   * `denom_traces` endpoint to get the path and base denom.
   *
   * @param {RESTClient} restClient - The RESTClient instance for the chain.
   * @param {string} denom - The IBC denom (must start with "ibc/").
   * @returns {Promise<string>} - The combined path and base denom (e.g., "transfer/channel-0/uinit").
   */
  async function getFullTrace(
    restClient: RESTClient,
    denom: string,
  ): Promise<string> {
    if (!denom.startsWith('ibc/')) {
      throw Error('Not an IBC denom')
    }

    const trace = await restClient.apiRequester.get<DenomTrace>(
      `/ibc/apps/transfer/v1/denom_traces/${denom}`,
    )
    return `${trace.denom_trace.path}/${trace.denom_trace.base_denom}`
  }

  /**
   *
   * Takes a denom from chain A (e.g., "uinit" or "ibc/...") and determines how it is
   * represented on chain B. This may result in a hashed IBC denom ("ibc/...") or
   * a "transfer/..." full trace string.
   *
   * 1. If the input denom starts with "ibc/", retrieve the original full trace using `getFullTrace`.
   * 2. If the resulting full trace starts with "transfer/{chainAChannel}/...", it indicates
   *    the token originally came from chain B (unwind logic).
   * 3. Otherwise, prepend "transfer/{chainBChannel}/..." (wind logic).
   * 4. Finally, if the resulting string begins with "transfer/", convert it to an IBC hash
   *    using `makeIBCHash`. Otherwise, return it as is.
   *
   * @param {RESTClient} restClient - The RESTClient for chain A.
   * @param {string} denom - The denom used on chain A (e.g., "uinit" or "ibc/...").
   * @param {string} chainAChannel - The channel ID on chain A (e.g., "channel-1").
   * @param {string} chainBChannel - The channel ID on chain B (e.g., "channel-2").
   * @returns {Promise<string>} - The resulting IBC denom (e.g., "ibc/...") or a "transfer/..." full trace.
   */
  export async function ibcDenom(
    restClient: RESTClient,
    denom: string,
    chainAChannel: string,
    chainBChannel: string,
  ): Promise<string> {
    let wind = true
    let fullTrace = denom

    // If denom starts with "ibc/", retrieve the original trace
    if (denom.startsWith('ibc/')) {
      fullTrace = await getFullTrace(restClient, denom)

      // If the token's trace starts with "transfer/chainAChannel/", token originated from chain B
      if (fullTrace.startsWith(`transfer/${chainAChannel}/`)) {
        wind = false
      }
    }

    // Depending on wind/unwind, construct the trace for chain B
    let fullTraceOnChainB: string
    if (wind) {
      // Wind: prepend "transfer/{chainBChannel}/"
      fullTraceOnChainB = `transfer/${chainBChannel}/${fullTrace}`
    } else {
      // Unwind: remove "transfer/{chainAChannel}/"
      fullTraceOnChainB = fullTrace.slice(`transfer/${chainAChannel}/`.length)
    }

    // If it starts with "transfer/", convert to an IBC hash; otherwise, return as is
    const denomInChainB = fullTraceOnChainB.startsWith('transfer/')
      ? makeIBCHash(fullTraceOnChainB)
      : fullTraceOnChainB

    return denomInChainB
  }

  async function main() {
    // Example usage of ibcDenom
    const denom = 'uinit' // or "ibc/..."
    const restClientChainA = new RESTClient('https://rest.testnet.initia.xyz')
    const channelA = 'channel-132' // Example channel ID for chain A
    const channelB = 'channel-0' // Example channel ID for chain B

    const ibcDenomStr = await ibcDenom(
      restClientChainA,
      denom,
      channelA,
      channelB,
    )
    console.log('Calculated IBC Denom:', ibcDenomStr)
  }

  main().catch((error) => {
    console.error('Error in main:', error)
  })
  ```
</Accordion>

4. (Optional) create an `images` folder to store the images for your rollup logo
   and token logos to link to in the two JSON files above.

### Submit a Pull Request

Once you have completed the above steps, you can submit a pull request to the
[Registry repository](https://github.com/initia-labs/initia-registry) to add
your rollup to the registry. Once your pull request is reviewed & merged by a
member of the Initia team, your rollup will be supported by the core Initia apps
shortly after.
