How to add to this coin list

  1. fork repo
  2. add TOKEN_ICON.svg (no larger than 100x100) to icons folder
  3. add RawCoinInfo to requestList.ts
  4. PR
  5. Shout in TG

Once PR is accepted, any authorized maintainer will be able to add the RawCoinInfo to our on-chain list by running yarn admin-cli -c config.yaml approve-symbol SYMBOL.

Fetching list

You can use the client provided in the included typescript sdk to fetch an updated list from the chain, or you could fetch the json file from github which is frequently updated:

Displaying RawCoinInfo

We recommend frontends display the following information for each coin:

  • name: full coin name, usually includes project name
  • symbol or official_symbol: short 3-6 letter representation
  • logo_url: coin logo

The reason we have both symbol field and official_symbol is that the symbol field is required to be unique within this registry, whereas for official_symbol there is no such requirement. For example, different bridge protocols may have their own bridged versions of USDC. They are allowed to use USDC as the official_symbol, but are required to use distinct symbols (e.g. xUSDC, yUSDC).

In a complete RawCoinInfo, we have these fields:

  • name: coin name, preferrably include project name
  • symbol: globally unique symbol within this coin registry
  • official_symbol: same as aptos_framework::coin::CoinInfo.symbol, duplicates allowed
  • coingecko_id: coingecko id. May be used by various clients to look up coin price
  • logo_url: URL to token logo, preferrably a githubusercontent url
  • project_url: URL to project
  • token_type: token address info
  • extensions: other informal info that you want to add, in the form of a list of string-string key-value pairs

Example:

{
  "name": "Aptos Coin",
  "symbol": "APT",
  "official_symbol": "APT",
  "coingecko_id": "aptos",
  "decimals": 8,
  "logo_url": "https://raw.githubusercontent.com/hippospace/aptos-coin-list/main/icons/APT.webp",
  "project_url": "https://aptoslabs.com/",
  "token_type": {
    "type": "0x1::aptos_coin::AptosCoin",
    "account_address": "0x1",
    "module_name": "aptos_coin",
    "struct_name": "AptosCoin"
  },
  "extensions": {
    "data": []
  }
},

Use the CoinList TS SDK

npm repo: @manahippo/coin-list

Client interface: here

Note that this npm repo contains a default list that's that's auto-generated by running

yarn cli -c config.yaml coin-list:query-fetch-full-list 0xb5d6dbc225e8c42cec66664ebbccaef2098107f699510613a0b90214f659bb46

The default list can be found here.

token-list

A permissionless, on-chain token list for aptos.

This coin list adopts a model where listing is separated into a 2-step process:

  1. Coin owner (owner of coin's module) registers CoinInfo into CoinRegistry
  2. CoinList users create their own list, and indicate which coins they'd like to add to their own list

The primary structs are:

  • CoinInfo: contains information about a particular coin, including items such as symbol, logo-url, project-url, coingecko-id, and a set of owner-defined extensions in the form of SimpleMap<String, String>.
  • CoinRegistry: there is a single CoinRegistry globally that contains all registered CoinInfo. Only module owner of coin type is allowed to edit its own information in the registry. (admins can also edit)
  • CoinList: each user can own a CoinList, which contains a subset of keys that the user is interested in.

CoinInfo is maintained exclusively in the CoinRegistry, and each user's CoinList only contains the set of included coin TypeInfo. This allows CoinInfo to be registered permissionlessly, yet each user still has control over which subset of all registered coins he wants to include into his own list.

Each user's full CoinList can be fetched in a single lookup using move-to-ts's query feature

const {client, account} = ...;
const app = new App(client).coin_list.coin_list;
const myList = await app.query_fetch_full_list(account, account.address(), []);

A major difference this design has with aptos_framework::coin::CoinInfo is that our CoinInfo do not have type parameters, and are therefore not stored as independent resources. This allows us to iterate over a set of CoinInfo values (not possible if they are type-parameterized).

CLI Usage

Usage: yarn adminCli [options] [command]

Options:
  -c, --config <path>                                path to your aptos config.yml (generated with "aptos init")
  -p, --profile <PROFILE>                            aptos config profile to use (default: "default")
  -h, --help                                         display help for command

Commands:
  show-list
  show-default-list
  write-default-list-json <network> <JSON_FILENAME>
  approve-symbol <TYPE_CoinType>
  update-symbol <TYPE_CoinType>
  update-all
  remove-symbol <TYPE_CoinType>
  register-coin-symbol <TYPE_CoinType>
  register-coin-all
  help [command]                                     display help for command
Usage: yarn cli [options] [command]

Move TS CLI generated by move-to-ts

Options:
  -c, --config <path>                                path to your aptos config.yml (generated with "aptos init")
  -p, --profile <PROFILE>                            aptos config profile to use (default: "default")
  -h, --help                                         display help for command

Commands:
  coin-list:add-approver-to-list <approver> [max_gas]
  coin-list:add-approver-to-registry <approver> [max_gas]
  coin-list:add-extension <TYPE_CoinType> <key> <value> [max_gas]
  coin-list:add-to-list <TYPE_CoinType> <list> [max_gas]
  coin-list:add-to-registry-by-approver <TYPE_CoinType> <name> <symbol> <coingecko_id> <logo_url> <project_url> <is_update> [max_gas]
  coin-list:add-to-registry-by-signer <TYPE_CoinType> <name> <symbol> <coingecko_id> <logo_url> <project_url> <is_update> [max_gas]
  coin-list:create-list [max_gas]
  coin-list:drop-extension <TYPE_CoinType> <key> <value> [max_gas]
  coin-list:initialize [max_gas]
  coin-list:remove-approver-from-list <approver> [max_gas]
  coin-list:remove-approver-from-registry <approver> [max_gas]
  coin-list:remove-from-list <TYPE_CoinType> [max_gas]
  coin-list:remove-from-registry-by-approver <TYPE_CoinType> [max_gas]
  coin-list:remove-from-registry-by-signer <TYPE_CoinType> [max_gas]
  devnet-coins:mint-to-wallet <TYPE_CoinType> <amount> [max_gas]
  coin-list:query-fetch-all-registered-coin-info [max_gas]
  coin-list:query-fetch-full-list <list_owner_addr> [max_gas]

You can use the TypeScript CLI to get the list owned by 0x498d8926f16eb9ca90cab1b3a26aa6f97a080b3fcbe6e83ae150b7243a00fb68

cd typescript
yarn install; yarn build
yarn cli -c APTOS_CONFIG_FILE coin-list:query-fetch-full-list 0x498d8926f16eb9ca90cab1b3a26aa6f97a080b3fcbe6e83ae150b7243a00fb68

Result:

{
  "coin_info_list": [
    {
      "name": "USD Coin",
      "symbol": "USDC",
      "coingecko_id": "usd-coin",
      "decimals": "8",
      "logo_url": "https://assets.coingecko.com/coins/images/6319/small/USD_Coin_icon.png?1547042389",
      "project_url": "project_url",
      "token_type": {
        "type": "0x498d8926f16eb9ca90cab1b3a26aa6f97a080b3fcbe6e83ae150b7243a00fb68::devnet_coins::DevnetUSDC",
        "account_address": "0x498d8926f16eb9ca90cab1b3a26aa6f97a080b3fcbe6e83ae150b7243a00fb68",
        "module_name": "devnet_coins",
        "struct_name": "DevnetUSDC"
      },
      "extensions": {
        "data": []
      }
    },
    {
      "name": "Tether",
      "symbol": "USDT",
      "coingecko_id": "tether",
      "decimals": "8",
      "logo_url": "https://assets.coingecko.com/coins/images/325/small/Tether-logo.png?1598003707",
      "project_url": "project_url",
      "token_type": {
        "type": "0x498d8926f16eb9ca90cab1b3a26aa6f97a080b3fcbe6e83ae150b7243a00fb68::devnet_coins::DevnetUSDT",
        "account_address": "0x498d8926f16eb9ca90cab1b3a26aa6f97a080b3fcbe6e83ae150b7243a00fb68",
        "module_name": "devnet_coins",
        "struct_name": "DevnetUSDT"
      },
      "extensions": {
        "data": []
      }
    },
    {
      "name": "Solana",
      "symbol": "SOL",
      "coingecko_id": "solana",
      "decimals": "8",
      "logo_url": "https://assets.coingecko.com/coins/images/4128/small/solana.png?1640133422",
      "project_url": "project_url",
      "token_type": {
        "type": "0x498d8926f16eb9ca90cab1b3a26aa6f97a080b3fcbe6e83ae150b7243a00fb68::devnet_coins::DevnetSOL",
        "account_address": "0x498d8926f16eb9ca90cab1b3a26aa6f97a080b3fcbe6e83ae150b7243a00fb68",
        "module_name": "devnet_coins",
        "struct_name": "DevnetSOL"
      },
      "extensions": {
        "data": []
      }
    },
    {
      "name": "Ethereum",
      "symbol": "ETH",
      "coingecko_id": "ethereum",
      "decimals": "8",
      "logo_url": "https://assets.coingecko.com/coins/images/279/small/ethereum.png?1595348880",
      "project_url": "project_url",
      "token_type": {
        "type": "0x498d8926f16eb9ca90cab1b3a26aa6f97a080b3fcbe6e83ae150b7243a00fb68::devnet_coins::DevnetETH",
        "account_address": "0x498d8926f16eb9ca90cab1b3a26aa6f97a080b3fcbe6e83ae150b7243a00fb68",
        "module_name": "devnet_coins",
        "struct_name": "DevnetETH"
      },
      "extensions": {
        "data": []
      }
    },
    {
      "name": "Bitcoin",
      "symbol": "BTC",
      "coingecko_id": "bitcoin",
      "decimals": "8",
      "logo_url": "https://assets.coingecko.com/coins/images/1/small/bitcoin.png?1547033579",
      "project_url": "project_url",
      "token_type": {
        "type": "0x498d8926f16eb9ca90cab1b3a26aa6f97a080b3fcbe6e83ae150b7243a00fb68::devnet_coins::DevnetBTC",
        "account_address": "0x498d8926f16eb9ca90cab1b3a26aa6f97a080b3fcbe6e83ae150b7243a00fb68",
        "module_name": "devnet_coins",
        "struct_name": "DevnetBTC"
      },
      "extensions": {
        "data": []
      }
    }
  ]
}

Or you can fetch the all registered CoinInfo using:

yarn cli -c APTOS_CONFIG_FILE coin-list:query-fetch-all-registered-coin-info

This would return more result than the previous command.