コンテンツにスキップ

ネームスペース情報を取得する⚓︎

初級

このチュートリアルでは、ネームスペース のプロパティ、その サブネームスペース、およびその下に定義された モザイク を取得する方法を説明します。

前提条件⚓︎

このチュートリアルではネットワークからデータを読み取るだけです。アカウントは必要ありません。

始める前に、開発環境をセットアップ してください。

完全なコード⚓︎

import json
import os
import urllib.request

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

NAMESPACE_NAME = os.getenv('NAMESPACE_NAME', 'company')
print(f'Namespace name: {NAMESPACE_NAME}')

try:
    # Fetch namespace information
    namespace_path = f'/namespace?namespace={NAMESPACE_NAME}'
    print(f'Fetching namespace information from {namespace_path}')
    with urllib.request.urlopen(f'{NODE_URL}{namespace_path}') as response:
        namespace_info = json.loads(response.read().decode())
        print('Namespace information:')
        print(f'  Name: {namespace_info["fqn"]}')
        print(f'  Owner: {namespace_info["owner"]}')
        lease_height = namespace_info['height']
        print(f'  Height: {lease_height}')

    # Compute the lease expiration
    LEASE_DURATION = 525600  # approximately one year of blocks
    with urllib.request.urlopen(f'{NODE_URL}/chain/height') as response:
        current_height = json.loads(response.read().decode())['height']
    expiration_height = lease_height + LEASE_DURATION
    print(f'\nCurrent chain height: {current_height}')
    print(f'Lease expiration height: {expiration_height}')
    print(f'Blocks until expiration: {expiration_height - current_height}')

    # List the subnamespaces
    owner = namespace_info['owner']
    subnamespaces_path = (
        f'/account/namespace/page'
        f'?address={owner}&parent={NAMESPACE_NAME}')
    print(f'\nFetching subnamespaces from {subnamespaces_path}')
    with urllib.request.urlopen(
        f'{NODE_URL}{subnamespaces_path}'
    ) as response:
        subnamespaces = json.loads(response.read().decode())['data']
        print(f'Subnamespaces of {NAMESPACE_NAME}: {len(subnamespaces)}')
        for subnamespace in subnamespaces:
            print(f'  {subnamespace["fqn"]}')

    # List the mosaics defined under the namespace
    mosaics_path = (
        f'/namespace/mosaic/definition/page?namespace={NAMESPACE_NAME}')
    print(f'\nFetching mosaic definitions from {mosaics_path}')
    with urllib.request.urlopen(f'{NODE_URL}{mosaics_path}') as response:
        mosaics = json.loads(response.read().decode())['data']
        print(f'Mosaics defined under {NAMESPACE_NAME}: {len(mosaics)}')
        for entry in mosaics:
            mosaic_id = entry['mosaic']['id']
            print(f'  {mosaic_id["namespaceId"]}:{mosaic_id["name"]}')

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 NAMESPACE_NAME = process.env.NAMESPACE_NAME || 'company';
console.log('Namespace name:', NAMESPACE_NAME);

try {
    // Fetch namespace information
    const namespacePath = `/namespace?namespace=${NAMESPACE_NAME}`;
    console.log('Fetching namespace information from', namespacePath);
    const namespaceResponse = await fetch(`${NODE_URL}${namespacePath}`);
    if (!namespaceResponse.ok)
        throw new Error(`HTTP error! status: ${namespaceResponse.status}`);

    const namespaceInfo = await namespaceResponse.json();
    console.log('Namespace information:');
    console.log('  Name:', namespaceInfo.fqn);
    console.log('  Owner:', namespaceInfo.owner);
    const leaseHeight = namespaceInfo.height;
    console.log('  Height:', leaseHeight);

    // Compute the lease expiration
    const LEASE_DURATION = 525600; // approximately one year of blocks
    const chainResponse = await fetch(`${NODE_URL}/chain/height`);
    const currentHeight = (await chainResponse.json()).height;
    const expirationHeight = leaseHeight + LEASE_DURATION;
    console.log('\nCurrent chain height:', currentHeight);
    console.log('Lease expiration height:', expirationHeight);
    console.log('Blocks until expiration:',
        expirationHeight - currentHeight);

    // List the subnamespaces
    const owner = namespaceInfo.owner;
    const subnamespacesPath = '/account/namespace/page' +
        `?address=${owner}&parent=${NAMESPACE_NAME}`;
    console.log('\nFetching subnamespaces from', subnamespacesPath);
    const subnamespacesResponse =
        await fetch(`${NODE_URL}${subnamespacesPath}`);
    const subnamespaces = (await subnamespacesResponse.json()).data;
    console.log(`Subnamespaces of ${NAMESPACE_NAME}:`,
        subnamespaces.length);
    for (const subnamespace of subnamespaces)
        console.log(`  ${subnamespace.fqn}`);

    // List the mosaics defined under the namespace
    const mosaicsPath =
        `/namespace/mosaic/definition/page?namespace=${NAMESPACE_NAME}`;
    console.log('\nFetching mosaic definitions from', mosaicsPath);
    const mosaicsResponse = await fetch(`${NODE_URL}${mosaicsPath}`);
    const mosaics = (await mosaicsResponse.json()).data;
    console.log(`Mosaics defined under ${NAMESPACE_NAME}:`,
        mosaics.length);
    for (const entry of mosaics) {
        const mosaicId = entry.mosaic.id;
        console.log(`  ${mosaicId.namespaceId}:${mosaicId.name}`);
    }

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

Download source

スニペットでは、NODE_URL 環境変数を使って NEM API ノードを指定します。 値が指定されていない場合は、デフォルトの テストネット ノードを使用します。

NAMESPACE_NAME 環境変数では、foofoo.bar のような、ドットで区切られた完全な 名前 で照会するネームスペースを指定します。 設定されていない場合は、テストネットに登録された ルートネームスペース である company を使用します。

コードの説明⚓︎

ネームスペース情報を取得する⚓︎

    # Fetch namespace information
    namespace_path = f'/namespace?namespace={NAMESPACE_NAME}'
    print(f'Fetching namespace information from {namespace_path}')
    with urllib.request.urlopen(f'{NODE_URL}{namespace_path}') as response:
        namespace_info = json.loads(response.read().decode())
        print('Namespace information:')
        print(f'  Name: {namespace_info["fqn"]}')
        print(f'  Owner: {namespace_info["owner"]}')
        lease_height = namespace_info['height']
        print(f'  Height: {lease_height}')
    // Fetch namespace information
    const namespacePath = `/namespace?namespace=${NAMESPACE_NAME}`;
    console.log('Fetching namespace information from', namespacePath);
    const namespaceResponse = await fetch(`${NODE_URL}${namespacePath}`);
    if (!namespaceResponse.ok)
        throw new Error(`HTTP error! status: ${namespaceResponse.status}`);

    const namespaceInfo = await namespaceResponse.json();
    console.log('Namespace information:');
    console.log('  Name:', namespaceInfo.fqn);
    console.log('  Owner:', namespaceInfo.owner);
    const leaseHeight = namespaceInfo.height;
    console.log('  Height:', leaseHeight);

/namespace GET エンドポイントは、次の内容を含むネームスペースの現在のプロパティを取得します。

リースの有効期限を計算する⚓︎

    # Compute the lease expiration
    LEASE_DURATION = 525600  # approximately one year of blocks
    with urllib.request.urlopen(f'{NODE_URL}/chain/height') as response:
        current_height = json.loads(response.read().decode())['height']
    expiration_height = lease_height + LEASE_DURATION
    print(f'\nCurrent chain height: {current_height}')
    print(f'Lease expiration height: {expiration_height}')
    print(f'Blocks until expiration: {expiration_height - current_height}')
    // Compute the lease expiration
    const LEASE_DURATION = 525600; // approximately one year of blocks
    const chainResponse = await fetch(`${NODE_URL}/chain/height`);
    const currentHeight = (await chainResponse.json()).height;
    const expirationHeight = leaseHeight + LEASE_DURATION;
    console.log('\nCurrent chain height:', currentHeight);
    console.log('Lease expiration height:', expirationHeight);
    console.log('Blocks until expiration:',
        expirationHeight - currentHeight);

ネームスペースが永久に所有されることはありません。 ルートネームスペースは 525600 ブロック(およそ 1 年)リース を受け、期限切れになる前に更新する必要があります。 サブネームスペースは個別にリースされず、ルートネームスペースと同時に期限切れになります。

有効期限の高さは API レスポンスに含まれませんが、ネームスペースの高さにリース期間を加えて導出できます。 これを /chain/height GET が返す現在のチェーン高と比較すると、ネームスペースの期限切れまでに残っているブロック数がわかります。

サブネームスペースを一覧表示する⚓︎

    # List the subnamespaces
    owner = namespace_info['owner']
    subnamespaces_path = (
        f'/account/namespace/page'
        f'?address={owner}&parent={NAMESPACE_NAME}')
    print(f'\nFetching subnamespaces from {subnamespaces_path}')
    with urllib.request.urlopen(
        f'{NODE_URL}{subnamespaces_path}'
    ) as response:
        subnamespaces = json.loads(response.read().decode())['data']
        print(f'Subnamespaces of {NAMESPACE_NAME}: {len(subnamespaces)}')
        for subnamespace in subnamespaces:
            print(f'  {subnamespace["fqn"]}')
    // List the subnamespaces
    const owner = namespaceInfo.owner;
    const subnamespacesPath = '/account/namespace/page' +
        `?address=${owner}&parent=${NAMESPACE_NAME}`;
    console.log('\nFetching subnamespaces from', subnamespacesPath);
    const subnamespacesResponse =
        await fetch(`${NODE_URL}${subnamespacesPath}`);
    const subnamespaces = (await subnamespacesResponse.json()).data;
    console.log(`Subnamespaces of ${NAMESPACE_NAME}:`,
        subnamespaces.length);
    for (const subnamespace of subnamespaces)
        console.log(`  ${subnamespace.fqn}`);

ネームスペースの子を直接返すエンドポイントはありません。 ただし、サブネームスペースは常にルートネームスペースの所有者を共有する ため、そのアカウントが所有するネームスペースを照会すれば見つけられます。

/account/namespace/page GET エンドポイントは、アカウントが所有するネームスペースを返します。 オプションの parent パラメーターを使うと、指定したネームスペースのサブネームスペースだけに結果を制限できます。 前の手順で取得したネームスペース所有者と照会したネームスペースを parent の値として使うと、そのサブネームスペースが返されます。

ネームスペースのモザイクを一覧表示する⚓︎

    # List the mosaics defined under the namespace
    mosaics_path = (
        f'/namespace/mosaic/definition/page?namespace={NAMESPACE_NAME}')
    print(f'\nFetching mosaic definitions from {mosaics_path}')
    with urllib.request.urlopen(f'{NODE_URL}{mosaics_path}') as response:
        mosaics = json.loads(response.read().decode())['data']
        print(f'Mosaics defined under {NAMESPACE_NAME}: {len(mosaics)}')
        for entry in mosaics:
            mosaic_id = entry['mosaic']['id']
            print(f'  {mosaic_id["namespaceId"]}:{mosaic_id["name"]}')
    // List the mosaics defined under the namespace
    const mosaicsPath =
        `/namespace/mosaic/definition/page?namespace=${NAMESPACE_NAME}`;
    console.log('\nFetching mosaic definitions from', mosaicsPath);
    const mosaicsResponse = await fetch(`${NODE_URL}${mosaicsPath}`);
    const mosaics = (await mosaicsResponse.json()).data;
    console.log(`Mosaics defined under ${NAMESPACE_NAME}:`,
        mosaics.length);
    for (const entry of mosaics) {
        const mosaicId = entry.mosaic.id;
        console.log(`  ${mosaicId.namespaceId}:${mosaicId.name}`);
    }

モザイクは常に ネームスペースの下に定義 され、関連するモザイクをまとめるプレフィックスとして機能します。

/namespace/mosaic/definition/page GET エンドポイントは、照会した名前とネームスペースが完全に一致するモザイクごとに 1 つの定義を返します。 より深いサブネームスペース(foo を照会したときの foo.bar:baz など)で定義されたモザイクは含まれません。 それらも一覧に含めるには、前の手順で見つかった各サブネームスペースについて、この照会を繰り返してください。

出力⚓︎

以下の出力は、テストネットの company ネームスペースを照会した場合の実行例です。

Using node http://libertalia.nemtest.net:7890
Namespace name: company
Fetching namespace information from /namespace?namespace=company
Namespace information:
  Name: company
  Owner: TBONKWCOWBZYZB2I5JD3LSDBQVBYHB757VN3SKPP
  Height: 625711

Current chain height: 655420
Lease expiration height: 1151311
Blocks until expiration: 495891

Fetching subnamespaces from /account/namespace/page?address=TBONKWCOWBZYZB2I5JD3LSDBQVBYHB757VN3SKPP&parent=company
Subnamespaces of company: 1
  company.division

Fetching mosaic definitions from /namespace/mosaic/definition/page?namespace=company
Mosaics defined under company: 1
  company:token

出力の要点は次のとおりです。

  • ネームスペース名(5 行目): 照会したネームスペース company。 ドットを含まないため、ルートネームスペースです。

  • 所有者(6 行目): 現在ネームスペースを所有するアカウント。

  • 高さ(7 行目): 現在の所有権期間が開始したブロックの高さ。

  • リースの有効期限(9~11 行目): 有効期限の高さは、所有権の高さにリース期間 525600 ブロックを加えた値です。 現在のチェーン高を引くと、有効期限までに残っているブロック数がわかります。

  • サブネームスペース(14~15 行目): company の下に company.division というサブネームスペースが 1 つ存在します。

  • モザイク(18~19 行目): ネームスペースの直下に company:token というモザイクが 1 つ定義されています。

まとめ⚓︎

このチュートリアルでは、次の方法を説明しました。

手順 関連ドキュメント
ネームスペースのプロパティを取得する /namespace GET
リースの有効期限を計算する /chain/height GET
サブネームスペースを一覧表示する /account/namespace/page GET
ネームスペースのモザイクを一覧表示する /namespace/mosaic/definition/page GET