The code follows the same pattern as the Registering a Root Namespace tutorial.
This section focuses only on the key differences.
For detailed explanations of the common steps (setting up the account, fetching network time and fees, and announcing),
see Registering a Root Namespace.
# Build the transactionroot_namespace_name='ns_root'child_namespace_name=f'sub_{int(time.time())}'full_namespace_name=(f'{root_namespace_name}.{child_namespace_name}')print(f'Creating child namespace: {full_namespace_name}')# Generate the parent namespace ID from the root namespace nameparent_id=generate_namespace_id(root_namespace_name)print(f' Parent namespace ID: {hex(parent_id)}')transaction=facade.transaction_factory.create({'type':'namespace_registration_transaction_v1','signer_public_key':signer_key_pair.public_key,'deadline':timestamp.add_hours(2).timestamp,'registration_type':'child','parent_id':parent_id,'name':child_namespace_name})transaction.fee=Amount(fee_mult*transaction.size)
// Build the transactionconstrootNamespaceName='ns_root';constchildNamespaceName=`sub_${Date.now()}`;constfullNamespaceName=`${rootNamespaceName}.${childNamespaceName}`;console.log('Creating child namespace:',fullNamespaceName);// Generate the parent namespace ID from the root nameconstparentId=generateNamespaceId(rootNamespaceName);console.log('Parent namespace ID:',`0x${parentId.toString(16)}`);consttransaction=facade.transactionFactory.create({type:'namespace_registration_transaction_v1',signerPublicKey:signerKeyPair.publicKey.toString(),deadline:timestamp.addHours(2).timestamp,registrationType:'child',parentId:parentId,name:childNamespaceName});transaction.fee=newmodels.Amount(feeMult*transaction.size);
The main difference when registering a subnamespace is in the transaction descriptor:
Registration type: The value child indicates a subnamespace (child namespace) is being created.
Use root to register a root namespace instead.
Parent ID: Instead of specifying a duration, you provide the namespace ID of the parent namespace.
The parent must be either a root namespace or another child namespace (if creating a third-level namespace).
The parent namespace ID is calculated from its name using .
Name: The name of the subnamespace.
This name follows the same rules as root namespace names: lowercase letters, numbers, hyphens, and underscores,
starting with a letter or number, up to 64 characters.
Note that this is just the name of the subnamespace, not the full path.
For example, to create company.product, where company is the root, you would set name: 'product' and
parent_id: generateNamespaceId('company').
To ensure the subnamespace name is unique across multiple runs of the tutorial, a timestamp is added to the name.
In practice, programs would use a fixed name for their namespaces.
The subnamespace automatically inherits the expiration time of its root namespace.
When the root expires, all subnamespaces expire with it.
Unlike the transaction fee, the lease fee is not included in the transaction request.
For subnamespaces, this fee is fixed regardless of duration.
The network deducts the lease fee automatically when the transaction is confirmed,
so you do not need to specify it in the transaction.
The transaction is then signed, announced, and confirmed following the same process as in
Registering a Root Namespace.
// Retrieve the namespaceconstnamespaceId=generateNamespaceId(childNamespaceName,parentId);console.log('Child namespace ID:',`${namespaceId} (0x${namespaceId.toString(16)})`);constnamespacePath=`/namespaces/${namespaceId.toString(16)}`;console.log('Fetching namespace information from',namespacePath);constnamespaceResponse=awaitfetch(`${NODE_URL}${namespacePath}`);constnamespaceJSON=awaitnamespaceResponse.json();constnamespaceInfo=namespaceJSON.namespace;console.log('Namespace information:');console.log(' Registration type:',namespaceInfo.registrationType);constownerAddress=newmodels.Address(Uint8Array.from(Buffer.from(namespaceInfo.ownerAddress,'hex')));console.log(' Owner address:',ownerAddress.toString());console.log(' Parent ID:',namespaceInfo.parentId);console.log(' Depth:',namespaceInfo.depth);console.log(' Level 0:',namespaceInfo.level0);if(namespaceInfo.depth>=1){console.log(' Level 1:',namespaceInfo.level1);}if(namespaceInfo.depth>=2&&namespaceInfo.level2){console.log(' Level 2:',namespaceInfo.level2);}console.log(' Start height:',namespaceInfo.startHeight);console.log(' End height:',namespaceInfo.endHeight);
To verify the subnamespace was registered, the code retrieves it from the network
using the /namespaces/{namespaceId}GET endpoint and displays its properties.
The subnamespace ID is computed using .
This function takes both the subnamespace name and the parent ID,
applying a deterministic hashing algorithm to produce the child namespace ID.
A successful response confirms the subnamespace was registered and is active on the network.
Subnamespace registered but not linked yet
A subnamespace becomes useful when it serves as an alias for a mosaic or an account.
Link the subnamespace to an identifier using the guides in Next Steps.
Using node https://reference.symboltest.net:3001
Signer address: TCHBDENCLKEBILBPWP3JPB2XNY64OE7PYHHE32I
Fetching current network time from /node/time
Network time: 99282637399 ms since nemesis
Fetching recommended fees from /network/fees/transaction
Fee multiplier: 100
Creating child namespace: ns_root.sub_1766533103
Parent namespace ID: 0xb0786316d5c1d9dd
Built transaction:
{
"signature": "9E91F08855D1911BE7208BB3441ACF8AE18EBEB529867D6DAC8552A837E17AA2F05BEBAE510950D5194E0837C4A6E780138CCF29A065F55C05A76CEF6AFA610E",
"signer_public_key": "3B6A27BCCEB6A42D62A3A8D02A6F0D73653215771DE243A63AC048A18B59DA29",
"version": 1,
"network": 152,
"type": 16718,
"fee": "16000",
"deadline": "99289837399",
"parent_id": "12716022497607277021",
"id": "11305240440531381773",
"registration_type": 1,
"name": "7375625f31373636353333313033"
}
Transaction hash: 43962A040342198E485F5E91364CA0270F737C56E58909FE03FE3F02AD97CA56
Announcing namespace registration to /transactions
Response: {"message":"packet 9 was pushed to the network via /transactions"}
Waiting for namespace registration confirmation...
Transaction status: unconfirmed
Transaction status: confirmed
Namespace registration confirmed in 19 seconds
Child namespace ID: 11305240440531381773 (0x9ce448486e40ee0d)
Fetching namespace information from /namespaces/9ce448486e40ee0d
Namespace information:
Registration type: 1
Owner address: TCHBDENCLKEBILBPWP3JPB2XNY64OE7PYHHE32I
Parent ID: B0786316D5C1D9DD
Depth: 2
Level 0: B0786316D5C1D9DD
Level 1: 9CE448486E40EE0D
Start height: 2956766
End height: 3046046
Some highlights from the output:
Full namespace path (line 7): The subnamespace ns_root.sub_1766533103 shows the full hierarchical name.
Parent namespace ID (lines 8, 33): The parent ID 0xb0786316d5c1d9dd links this subnamespace to its root.
Fee (line 16): The transaction fee of 0.016 XYM is calculated as the transaction size
multiplied by the fee multiplier. The lease fee is deducted separately
by the network when the transaction is confirmed.
ID and name (lines 19, 21): The id field shows the subnamespace ID as a decimal number, while name contains
only the child portion encoded as hexadecimal (for example, 7375625f... decodes to sub_1...).
Child namespace ID (line 30): Shows both decimal and hexadecimal representations to match the id field on
line 19.
Registration type (line 34): The value 1 indicates a subnamespace (versus 0 for root namespaces).
Owner address (line 35): The account that registered the namespace, which must be the same as the root
namespace owner.
Depth (line 36): The depth of 2 indicates there are 2 levels in the namespace hierarchy.
Level 0 is the root namespace, and level 1 is this subnamespace.
Levels (lines 37-38): The full hierarchical path. level0 contains the root namespace ID, and level1
contains the child ID. If depth were 3, level2 would contain the grandchild ID.
Start and end heights (lines 39-40): These values are inherited from the root namespace, not set independently.
The transaction hash printed in the output can also be used to search for the transaction
in the Symbol Testnet Explorer.