Skip to content

Getting Mosaic Information⚓︎

BEGINNER

Every mosaic on NEM has a set of on-chain properties such as supply, divisibility, and transfer rules.

This tutorial shows how to retrieve a mosaic's properties and its current supply.

Prerequisites⚓︎

This tutorial only reads data from the network. No account is required.

Before you start, make sure to set up your development environment.

Full Code⚓︎

import json
import os
import urllib.request

NODE_URL = os.getenv('NODE_URL', 'http://libertalia.nemtest.net:7890')
print(f'Using node {NODE_URL}')

MOSAIC_ID = os.getenv('MOSAIC_ID', 'nem:xem')
print(f'Mosaic ID: {MOSAIC_ID}')

try:
    # Fetch mosaic information
    mosaic_path = f'/mosaic/definition?mosaicId={MOSAIC_ID}'
    print(f'Fetching mosaic information from {mosaic_path}')
    with urllib.request.urlopen(f'{NODE_URL}{mosaic_path}') as response:
        response_json = json.loads(response.read().decode())
        mosaic_id = response_json['id']
        full_name = f'{mosaic_id["namespaceId"]}:{mosaic_id["name"]}'
        print('Mosaic information:')
        print(f'  Mosaic ID: {full_name}')
        print(f'  Description: {response_json["description"]}')
        print(f'  Creator: {response_json["creator"]}')
        properties = {
            prop['name']: prop['value']
            for prop in response_json['properties']
        }
        divisibility = int(properties['divisibility'])
        print(f'  Divisibility: {divisibility}')
        print(f'  Initial supply: {properties["initialSupply"]}')
        print(f'  Supply mutable: {properties["supplyMutable"]}')
        print(f'  Transferable: {properties["transferable"]}')
        levy = response_json['levy']
        print(f'  Levy: {levy if levy else "none"}')

    # Fetch the current supply
    supply_path = f'/mosaic/supply?mosaicId={MOSAIC_ID}'
    print(f'\nFetching current supply from {supply_path}')
    with urllib.request.urlopen(f'{NODE_URL}{supply_path}') as response:
        supply_info = json.loads(response.read().decode())
        supply = supply_info['supply']
        print(f'  Current supply: {supply}')

    # Convert the supply to atomic units
    atomic = supply * 10 ** divisibility
    print(f'\nSupply in atomic units: {atomic}')

except Exception as e:
    print(e)

Download source

const NODE_URL = process.env.NODE_URL ||
    'http://libertalia.nemtest.net:7890';
console.log('Using node', NODE_URL);

const MOSAIC_ID = process.env.MOSAIC_ID || 'nem:xem';
console.log('Mosaic ID:', MOSAIC_ID);

try {
    // Fetch mosaic information
    const mosaicPath = `/mosaic/definition?mosaicId=${MOSAIC_ID}`;
    console.log('Fetching mosaic information from', mosaicPath);
    const mosaicResponse = await fetch(`${NODE_URL}${mosaicPath}`);
    if (!mosaicResponse.ok)
        throw new Error(`HTTP error! status: ${mosaicResponse.status}`);

    const mosaicJSON = await mosaicResponse.json();
    const fullName = `${mosaicJSON.id.namespaceId}:${mosaicJSON.id.name}`;
    console.log('Mosaic information:');
    console.log(`  Mosaic ID: ${fullName}`);
    console.log('  Description:', mosaicJSON.description);
    console.log('  Creator:', mosaicJSON.creator);
    const properties = Object.fromEntries(mosaicJSON.properties
        .map(property => [property.name, property.value]));
    const divisibility = parseInt(properties.divisibility, 10);
    console.log('  Divisibility:', divisibility);
    console.log('  Initial supply:', properties.initialSupply);
    console.log('  Supply mutable:', properties.supplyMutable);
    console.log('  Transferable:', properties.transferable);
    const hasLevy = 0 !== Object.keys(mosaicJSON.levy).length;
    console.log('  Levy:', hasLevy ? mosaicJSON.levy : 'none');

    // Fetch the current supply
    const supplyPath = `/mosaic/supply?mosaicId=${MOSAIC_ID}`;
    console.log('\nFetching current supply from', supplyPath);
    const supplyResponse = await fetch(`${NODE_URL}${supplyPath}`);
    const supplyInfo = await supplyResponse.json();
    const supply = supplyInfo.supply;
    console.log('  Current supply:', supply);

    // Convert the supply to atomic units
    const atomic = BigInt(supply) * (10n ** BigInt(divisibility));
    console.log(`\nSupply in atomic units: ${atomic}`);

} catch (e) {
    console.error(e.message);
}

Download source

The snippet uses the NODE_URL environment variable to set the NEM API node. If no value is provided, a default testnet node is used.

The MOSAIC_ID environment variable specifies which mosaic to query, given as its fully qualified name. If not set, it defaults to the XEM mosaic (nem:xem).

Code Explanation⚓︎

Fetching Mosaic Information⚓︎

    # Fetch mosaic information
    mosaic_path = f'/mosaic/definition?mosaicId={MOSAIC_ID}'
    print(f'Fetching mosaic information from {mosaic_path}')
    with urllib.request.urlopen(f'{NODE_URL}{mosaic_path}') as response:
        response_json = json.loads(response.read().decode())
        mosaic_id = response_json['id']
        full_name = f'{mosaic_id["namespaceId"]}:{mosaic_id["name"]}'
        print('Mosaic information:')
        print(f'  Mosaic ID: {full_name}')
        print(f'  Description: {response_json["description"]}')
        print(f'  Creator: {response_json["creator"]}')
        properties = {
            prop['name']: prop['value']
            for prop in response_json['properties']
        }
        divisibility = int(properties['divisibility'])
        print(f'  Divisibility: {divisibility}')
        print(f'  Initial supply: {properties["initialSupply"]}')
        print(f'  Supply mutable: {properties["supplyMutable"]}')
        print(f'  Transferable: {properties["transferable"]}')
        levy = response_json['levy']
        print(f'  Levy: {levy if levy else "none"}')
    // Fetch mosaic information
    const mosaicPath = `/mosaic/definition?mosaicId=${MOSAIC_ID}`;
    console.log('Fetching mosaic information from', mosaicPath);
    const mosaicResponse = await fetch(`${NODE_URL}${mosaicPath}`);
    if (!mosaicResponse.ok)
        throw new Error(`HTTP error! status: ${mosaicResponse.status}`);

    const mosaicJSON = await mosaicResponse.json();
    const fullName = `${mosaicJSON.id.namespaceId}:${mosaicJSON.id.name}`;
    console.log('Mosaic information:');
    console.log(`  Mosaic ID: ${fullName}`);
    console.log('  Description:', mosaicJSON.description);
    console.log('  Creator:', mosaicJSON.creator);
    const properties = Object.fromEntries(mosaicJSON.properties
        .map(property => [property.name, property.value]));
    const divisibility = parseInt(properties.divisibility, 10);
    console.log('  Divisibility:', divisibility);
    console.log('  Initial supply:', properties.initialSupply);
    console.log('  Supply mutable:', properties.supplyMutable);
    console.log('  Transferable:', properties.transferable);
    const hasLevy = 0 !== Object.keys(mosaicJSON.levy).length;
    console.log('  Levy:', hasLevy ? mosaicJSON.levy : 'none');

The /mosaic/definition GET endpoint retrieves the definition of a mosaic, including:

  • Description: Text describing the mosaic.
  • Creator: The public key of the account that created the mosaic.
  • Properties: The mosaic's behavioral properties:
    • Divisibility: The number of decimal places the mosaic supports. For example, XEM has a divisibility of 6, meaning 1 XEM equals 1'000'000 atomic units.
    • Initial supply: The supply at creation time, expressed in whole units.
    • Supply mutability: Whether the creator can change the supply after creation.
    • Transferability: Whether the mosaic can be freely sent between accounts or only to and from the creator.
  • Levy: An optional extra fee paid to a third account whenever the mosaic is transferred.

Fetching the Current Supply⚓︎

    # Fetch the current supply
    supply_path = f'/mosaic/supply?mosaicId={MOSAIC_ID}'
    print(f'\nFetching current supply from {supply_path}')
    with urllib.request.urlopen(f'{NODE_URL}{supply_path}') as response:
        supply_info = json.loads(response.read().decode())
        supply = supply_info['supply']
        print(f'  Current supply: {supply}')
    // Fetch the current supply
    const supplyPath = `/mosaic/supply?mosaicId=${MOSAIC_ID}`;
    console.log('\nFetching current supply from', supplyPath);
    const supplyResponse = await fetch(`${NODE_URL}${supplyPath}`);
    const supplyInfo = await supplyResponse.json();
    const supply = supplyInfo.supply;
    console.log('  Current supply:', supply);

The definition only records the initial supply. For mosaics with mutable supply, the current value can differ, so the /mosaic/supply GET endpoint returns the supply currently in circulation, expressed in whole units.

Converting to Atomic Units⚓︎

    # Convert the supply to atomic units
    atomic = supply * 10 ** divisibility
    print(f'\nSupply in atomic units: {atomic}')
    // Convert the supply to atomic units
    const atomic = BigInt(supply) * (10n ** BigInt(divisibility));
    console.log(`\nSupply in atomic units: ${atomic}`);

The endpoint reports supply in whole units, but transaction quantities are expressed in atomic units. To convert from whole to atomic units, the code multiplies the supply by 10 raised to the mosaic's divisibility.

For XEM (divisibility 6), a supply of 8'999'999'999 whole units equals 8'999'999'999'000'000' atomic units.

Output⚓︎

The output shown below corresponds to a typical run of the program, querying the XEM mosaic on testnet.

Using node http://libertalia.nemtest.net:7890
Mosaic ID: nem:xem
Fetching mosaic information from /mosaic/definition?mosaicId=nem:xem
Mosaic information:
  Mosaic ID: nem:xem
  Description: reserved xem mosaic
  Creator: 3e82e1c1e4a75adaa3cba8c101c3cd31d9817a2eb966eb3b511fb2ed45b8e262
  Divisibility: 6
  Initial supply: 8999999999
  Supply mutable: false
  Transferable: true
  Levy: none

Fetching current supply from /mosaic/supply?mosaicId=nem:xem
  Current supply: 8999999999

Supply in atomic units: 8999999999000000

Some highlights from the output:

  • Mosaic ID (line 5): The XEM mosaic identifier, the fully qualified name nem:xem.

  • Description (line 6): Text that describes the mosaic, set by its creator.

  • Creator (line 7): The public key of the account that created the mosaic.

  • Divisibility (line 8): The value 6 means 1 XEM = 1'000'000 (106) atomic units.

  • Initial supply (line 9): The supply at creation time, in whole units.

  • Supply mutable (line 10): The value false means the XEM supply can never change.

  • Transferable (line 11): The value true means XEM can be freely sent between accounts.

  • Levy (line 12): XEM transfers carry no additional mosaic fee.

  • Current supply (line 15): The supply currently in circulation, identical to the initial supply because XEM is not mutable.

  • Supply in atomic units (line 17): The supply converted from whole units to atomic units using the mosaic's divisibility.

Conclusion⚓︎

This tutorial showed how to:

Step Related documentation
Fetch the mosaic definition /mosaic/definition GET
Fetch the current supply /mosaic/supply GET

Next Steps⚓︎