importjsonimportosimporturllib.requestNODE_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 informationnamespace_path=f'/namespace?namespace={NAMESPACE_NAME}'print(f'Fetching namespace information from {namespace_path}')withurllib.request.urlopen(f'{NODE_URL}{namespace_path}')asresponse: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 expirationLEASE_DURATION=525600# approximately one year of blockswithurllib.request.urlopen(f'{NODE_URL}/chain/height')asresponse:current_height=json.loads(response.read().decode())['height']expiration_height=lease_height+LEASE_DURATIONprint(f'\nCurrent chain height: {current_height}')print(f'Lease expiration height: {expiration_height}')print(f'Blocks until expiration: {expiration_height-current_height}')# List the subnamespacesowner=namespace_info['owner']subnamespaces_path=(f'/account/namespace/page'f'?address={owner}&parent={NAMESPACE_NAME}')print(f'\nFetching subnamespaces from {subnamespaces_path}')withurllib.request.urlopen(f'{NODE_URL}{subnamespaces_path}')asresponse:subnamespaces=json.loads(response.read().decode())['data']print(f'Subnamespaces of {NAMESPACE_NAME}: {len(subnamespaces)}')forsubnamespaceinsubnamespaces:print(f' {subnamespace["fqn"]}')# List the mosaics defined under the namespacemosaics_path=(f'/namespace/mosaic/definition/page?namespace={NAMESPACE_NAME}')print(f'\nFetching mosaic definitions from {mosaics_path}')withurllib.request.urlopen(f'{NODE_URL}{mosaics_path}')asresponse:mosaics=json.loads(response.read().decode())['data']print(f'Mosaics defined under {NAMESPACE_NAME}: {len(mosaics)}')forentryinmosaics:mosaic_id=entry['mosaic']['id']print(f' {mosaic_id["namespaceId"]}:{mosaic_id["name"]}')exceptExceptionase:print(e)
constNODE_URL=process.env.NODE_URL||'http://libertalia.nemtest.net:7890';console.log('Using node',NODE_URL);constNAMESPACE_NAME=process.env.NAMESPACE_NAME||'company';console.log('Namespace name:',NAMESPACE_NAME);try{// Fetch namespace informationconstnamespacePath=`/namespace?namespace=${NAMESPACE_NAME}`;console.log('Fetching namespace information from',namespacePath);constnamespaceResponse=awaitfetch(`${NODE_URL}${namespacePath}`);if(!namespaceResponse.ok)thrownewError(`HTTP error! status: ${namespaceResponse.status}`);constnamespaceInfo=awaitnamespaceResponse.json();console.log('Namespace information:');console.log(' Name:',namespaceInfo.fqn);console.log(' Owner:',namespaceInfo.owner);constleaseHeight=namespaceInfo.height;console.log(' Height:',leaseHeight);// Compute the lease expirationconstLEASE_DURATION=525600;// approximately one year of blocksconstchainResponse=awaitfetch(`${NODE_URL}/chain/height`);constcurrentHeight=(awaitchainResponse.json()).height;constexpirationHeight=leaseHeight+LEASE_DURATION;console.log('\nCurrent chain height:',currentHeight);console.log('Lease expiration height:',expirationHeight);console.log('Blocks until expiration:',expirationHeight-currentHeight);// List the subnamespacesconstowner=namespaceInfo.owner;constsubnamespacesPath='/account/namespace/page'+`?address=${owner}&parent=${NAMESPACE_NAME}`;console.log('\nFetching subnamespaces from',subnamespacesPath);constsubnamespacesResponse=awaitfetch(`${NODE_URL}${subnamespacesPath}`);constsubnamespaces=(awaitsubnamespacesResponse.json()).data;console.log(`Subnamespaces of ${NAMESPACE_NAME}:`,subnamespaces.length);for(constsubnamespaceofsubnamespaces)console.log(` ${subnamespace.fqn}`);// List the mosaics defined under the namespaceconstmosaicsPath=`/namespace/mosaic/definition/page?namespace=${NAMESPACE_NAME}`;console.log('\nFetching mosaic definitions from',mosaicsPath);constmosaicsResponse=awaitfetch(`${NODE_URL}${mosaicsPath}`);constmosaics=(awaitmosaicsResponse.json()).data;console.log(`Mosaics defined under ${NAMESPACE_NAME}:`,mosaics.length);for(constentryofmosaics){constmosaicId=entry.mosaic.id;console.log(` ${mosaicId.namespaceId}:${mosaicId.name}`);}}catch(e){console.error(e.message);}
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 NAMESPACE_NAME environment variable specifies which namespace to query, given as its full dot-separated
name like foo or foo.bar.
If not set, it defaults to company, a root namespace registered on testnet.
The /namespaceGET endpoint retrieves the current properties of a namespace, including:
Name: The complete dot-separated identifier of the namespace,
from the root down to the queried level.
For example, foo is a root namespace and foo.bar is a subnamespace of foo.
fqn in the returned data structure stands for Fully-Qualified Name.
# Compute the lease expirationLEASE_DURATION=525600# approximately one year of blockswithurllib.request.urlopen(f'{NODE_URL}/chain/height')asresponse:current_height=json.loads(response.read().decode())['height']expiration_height=lease_height+LEASE_DURATIONprint(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 expirationconstLEASE_DURATION=525600;// approximately one year of blocksconstchainResponse=awaitfetch(`${NODE_URL}/chain/height`);constcurrentHeight=(awaitchainResponse.json()).height;constexpirationHeight=leaseHeight+LEASE_DURATION;console.log('\nCurrent chain height:',currentHeight);console.log('Lease expiration height:',expirationHeight);console.log('Blocks until expiration:',expirationHeight-currentHeight);
Namespaces are not owned permanently.
A root namespace is leased for 525600 blocks (approximately one year)
and must be renewed before it expires.
Subnamespaces are not leased individually, as they expire together with their root namespace.
The expiration height is not part of the API response, but it can be derived by adding the lease duration to the
namespace's height.
Comparing it with the current chain height, returned by /chain/heightGET, gives the number of blocks remaining before
the namespace expires.
# List the subnamespacesowner=namespace_info['owner']subnamespaces_path=(f'/account/namespace/page'f'?address={owner}&parent={NAMESPACE_NAME}')print(f'\nFetching subnamespaces from {subnamespaces_path}')withurllib.request.urlopen(f'{NODE_URL}{subnamespaces_path}')asresponse:subnamespaces=json.loads(response.read().decode())['data']print(f'Subnamespaces of {NAMESPACE_NAME}: {len(subnamespaces)}')forsubnamespaceinsubnamespaces:print(f' {subnamespace["fqn"]}')
// List the subnamespacesconstowner=namespaceInfo.owner;constsubnamespacesPath='/account/namespace/page'+`?address=${owner}&parent=${NAMESPACE_NAME}`;console.log('\nFetching subnamespaces from',subnamespacesPath);constsubnamespacesResponse=awaitfetch(`${NODE_URL}${subnamespacesPath}`);constsubnamespaces=(awaitsubnamespacesResponse.json()).data;console.log(`Subnamespaces of ${NAMESPACE_NAME}:`,subnamespaces.length);for(constsubnamespaceofsubnamespaces)console.log(` ${subnamespace.fqn}`);
There is no endpoint that returns the children of a namespace directly.
However, because subnamespaces always share the owner of their root
namespace, they can be found by querying the namespaces owned by that account.
The /account/namespace/pageGET endpoint returns the namespaces owned by an account, and its optional parent
parameter restricts the results to subnamespaces of a given namespace.
Using the namespace owner obtained in the previous step and the queried namespace as the parent value returns its
subnamespaces.
# List the mosaics defined under the namespacemosaics_path=(f'/namespace/mosaic/definition/page?namespace={NAMESPACE_NAME}')print(f'\nFetching mosaic definitions from {mosaics_path}')withurllib.request.urlopen(f'{NODE_URL}{mosaics_path}')asresponse:mosaics=json.loads(response.read().decode())['data']print(f'Mosaics defined under {NAMESPACE_NAME}: {len(mosaics)}')forentryinmosaics:mosaic_id=entry['mosaic']['id']print(f' {mosaic_id["namespaceId"]}:{mosaic_id["name"]}')
// List the mosaics defined under the namespaceconstmosaicsPath=`/namespace/mosaic/definition/page?namespace=${NAMESPACE_NAME}`;console.log('\nFetching mosaic definitions from',mosaicsPath);constmosaicsResponse=awaitfetch(`${NODE_URL}${mosaicsPath}`);constmosaics=(awaitmosaicsResponse.json()).data;console.log(`Mosaics defined under ${NAMESPACE_NAME}:`,mosaics.length);for(constentryofmosaics){constmosaicId=entry.mosaic.id;console.log(` ${mosaicId.namespaceId}:${mosaicId.name}`);}
Mosaics are always defined under a namespace, which acts as a prefix
grouping related mosaics together.
The /namespace/mosaic/definition/pageGET endpoint returns one definition for each mosaic whose namespace matches
the queried name exactly.
Mosaics defined under deeper subnamespaces (such as foo.bar:baz when querying foo) are not included.
To list those as well, repeat this query for each subnamespace found in the previous step.
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
Some highlights from the output:
Namespace name (line 5): The queried namespace, company.
Because it contains no dots, it is a root namespace.
Owner (line 6): The account that currently owns the namespace.
Height (line 7): The block height at which the current ownership period began.
Lease expiration (lines 9-11): The expiration height is the ownership height plus the lease duration of
525600 blocks.
Subtracting the current chain height shows how many blocks remain before expiration.
Subnamespaces (lines 14-15): One subnamespace exists under company: company.division.
Mosaics (lines 18-19): One mosaic is defined directly under the namespace: company:token.