importjsonimportosimporttimeimporturllib.requestfromsymbolchain.CryptoTypesimportPrivateKeyfromsymbolchain.facade.SymbolFacadeimportSymbolFacadefromsymbolchain.symbol.NetworkimportNetworkTimestampfromsymbolchain.symbol.IdGeneratorimport(generate_namespace_path,generate_mosaic_alias_id)fromsymbolchain.scimportAmountfromsymbolchain.symbol.NetworkimportAddressNODE_URL=os.getenv('NODE_URL','https://reference.symboltest.net:3001')print(f'Using node {NODE_URL}')SIGNER_PRIVATE_KEY=os.getenv('SIGNER_PRIVATE_KEY','0000000000000000000000000000000000000000000000000000000000000000')signer_key_pair=SymbolFacade.KeyPair(PrivateKey(SIGNER_PRIVATE_KEY))facade=SymbolFacade('testnet')signer_address=facade.network.public_key_to_address(signer_key_pair.public_key)print(f'Signer address: {signer_address}')namespace_name=os.getenv('NAMESPACE_NAME','my_namespace')print(f'Namespace name: {namespace_name}')namespace_id=generate_namespace_path(namespace_name)[-1]print(f'Namespace ID: {namespace_id} ({hex(namespace_id)})')# Target address to link the namespace totarget_address=Address(os.getenv('TARGET_ADDRESS','TCWYXKVYBMO4NBCUF3AXKJMXCGVSYQOS7ZG2TLI'))print(f'Target address: {target_address}')try:# Fetch current network timetime_path='/node/time'print(f'Fetching current network time from {time_path}')withurllib.request.urlopen(f'{NODE_URL}{time_path}')asresponse:response_json=json.loads(response.read().decode())receive_timestamp=(response_json['communicationTimestamps']['receiveTimestamp'])timestamp=NetworkTimestamp(int(receive_timestamp))print(f' Network time: {timestamp.timestamp} ms since nemesis')# Fetch recommended feesfee_path='/network/fees/transaction'print(f'Fetching recommended fees from {fee_path}')withurllib.request.urlopen(f'{NODE_URL}{fee_path}')asresponse:response_json=json.loads(response.read().decode())median_mult=response_json['medianFeeMultiplier']minimum_mult=response_json['minFeeMultiplier']fee_mult=max(median_mult,minimum_mult)print(f' Fee multiplier: {fee_mult}')# Build the alias transactiontransaction=facade.transaction_factory.create({'type':'address_alias_transaction_v1','signer_public_key':signer_key_pair.public_key,'deadline':timestamp.add_hours(2).timestamp,'namespace_id':namespace_id,'address':target_address,'alias_action':'link'})transaction.fee=Amount(fee_mult*transaction.size)# Sign transaction and generate final payloadsignature=facade.sign_transaction(signer_key_pair,transaction)json_payload=facade.transaction_factory.attach_signature(transaction,signature)print('Built transaction:')print(json.dumps(transaction.to_json(),indent=2))transaction_hash=facade.hash_transaction(transaction)print(f'Transaction hash: {transaction_hash}')# Announce transactionprint('Announcing address alias transaction to /transactions')request=urllib.request.Request(f'{NODE_URL}/transactions',data=json_payload.encode(),headers={'Content-Type':'application/json'},method='PUT')withurllib.request.urlopen(request)asresponse:print(f' Response: {response.read().decode()}')# Wait for confirmationprint('Waiting for transaction confirmation...')forattemptinrange(60):time.sleep(1)try:status_url=(f'{NODE_URL}/transactionStatus/{transaction_hash}')withurllib.request.urlopen(status_url)asresponse:status=json.loads(response.read().decode())print(f' Transaction status: {status["group"]}')ifstatus['group']=='confirmed':print('Address alias transaction confirmed in',attempt,'seconds')breakifstatus['group']=='failed':raiseException('Address alias transaction failed:',status['code'])excepturllib.error.HTTPError:print(' Transaction status: unknown')# Retrieve the namespace to verify the aliasnamespace_path=f'/namespaces/{namespace_id:x}'print(f'Fetching namespace information from {namespace_path}')withurllib.request.urlopen(f'{NODE_URL}{namespace_path}')asresponse:response_json=json.loads(response.read().decode())namespace_info=response_json['namespace']print('Alias information:')alias_type=namespace_info['alias']['type']print(f' Alias type: {alias_type}')ifalias_type==2:# ADDRESS typealiased_address_hex=namespace_info['alias']['address']aliased_address=Address(bytes.fromhex(aliased_address_hex))print(f' Linked address: {aliased_address}')# Send a transfer using the alias instead of a raw addressprint(f'Using alias in transfer: {namespace_name}')# Encode the namespace ID as a recipient address (24 bytes)# Byte 0: network byte (Network Identifier | 0x01 to indicate alias)# Bytes 1-8: namespace ID in little-endian# Bytes 9-23: zero paddingrecipient_id=generate_namespace_path(namespace_name)[-1]recipient_address=Address(bytes([facade.network.identifier|0x01])+recipient_id.to_bytes(8,'little')+bytes(15))transfer_tx=facade.transaction_factory.create({'type':'transfer_transaction_v1','signer_public_key':signer_key_pair.public_key,'deadline':timestamp.add_hours(2).timestamp,'recipient_address':recipient_address,'mosaics':[{'mosaic_id':generate_mosaic_alias_id('symbol.xym'),'amount':1_000_000# 1 XYM}]})print('Transfer transaction:')print(f' Recipient address (alias): {recipient_address}')exceptExceptionase:print(e)
import{PrivateKey}from'symbol-sdk';import{SymbolFacade,NetworkTimestamp,models,generateNamespacePath,generateMosaicAliasId}from'symbol-sdk/symbol';constNODE_URL=process.env.NODE_URL||'https://reference.symboltest.net:3001';console.log('Using node',NODE_URL);constSIGNER_PRIVATE_KEY=process.env.SIGNER_PRIVATE_KEY||'0000000000000000000000000000000000000000000000000000000000000000';constsignerKeyPair=newSymbolFacade.KeyPair(newPrivateKey(SIGNER_PRIVATE_KEY));constfacade=newSymbolFacade('testnet');constsignerAddress=facade.network.publicKeyToAddress(signerKeyPair.publicKey);console.log('Signer address:',signerAddress.toString());constnamespaceName=process.env.NAMESPACE_NAME||'my_namespace';console.log('Namespace name:',namespaceName);constnsPath=generateNamespacePath(namespaceName);constnamespaceId=nsPath[nsPath.length-1];console.log('Namespace ID:',`${namespaceId} (0x${namespaceId.toString(16)})`);// Target address to link the namespace toconsttargetAddress=newSymbolFacade.Address(process.env.TARGET_ADDRESS||'TCWYXKVYBMO4NBCUF3AXKJMXCGVSYQOS7ZG2TLI');console.log('Target address:',targetAddress.toString());try{// Fetch current network timeconsttimePath='/node/time';console.log('Fetching current network time from',timePath);consttimeResponse=awaitfetch(`${NODE_URL}${timePath}`);consttimeJSON=awaittimeResponse.json();constreceiveTimestamp=timeJSON.communicationTimestamps.receiveTimestamp;consttimestamp=newNetworkTimestamp(receiveTimestamp);console.log(' Network time:',timestamp.timestamp,'ms since nemesis');// Fetch recommended feesconstfeePath='/network/fees/transaction';console.log('Fetching recommended fees from',feePath);constfeeResponse=awaitfetch(`${NODE_URL}${feePath}`);constfeeJSON=awaitfeeResponse.json();constmedianMult=feeJSON.medianFeeMultiplier;constminimumMult=feeJSON.minFeeMultiplier;constfeeMult=Math.max(medianMult,minimumMult);console.log(' Fee multiplier:',feeMult);// Build the alias transactionconsttransaction=facade.transactionFactory.create({type:'address_alias_transaction_v1',signerPublicKey:signerKeyPair.publicKey.toString(),deadline:timestamp.addHours(2).timestamp,namespaceId:namespaceId,address:targetAddress,aliasAction:'link'});transaction.fee=newmodels.Amount(feeMult*transaction.size);// Sign transaction and generate final payloadconstsignature=facade.signTransaction(signerKeyPair,transaction);constjsonPayload=facade.transactionFactory.static.attachSignature(transaction,signature);console.log('Built transaction:');console.dir(transaction.toJson(),{colors:true});consttransactionHash=facade.hashTransaction(transaction).toString();console.log('Transaction hash:',transactionHash);// Announce transactionconsole.log('Announcing address alias transaction to /transactions');constannounceResponse=awaitfetch(`${NODE_URL}/transactions`,{method:'PUT',headers:{'Content-Type':'application/json'},body:jsonPayload});console.log(' Response:',awaitannounceResponse.text());// Wait for confirmationconsole.log('Waiting for transaction confirmation...');for(letattempt=0;attempt<60;attempt++){awaitnewPromise(resolve=>setTimeout(resolve,1000));try{conststatusUrl=`${NODE_URL}/transactionStatus/${transactionHash}`;conststatusResponse=awaitfetch(statusUrl);if(!statusResponse.ok){console.log(' Transaction status: unknown');continue;}conststatus=awaitstatusResponse.json();console.log(' Transaction status:',status.group);if(status.group==='confirmed'){console.log('Address alias transaction confirmed in',attempt,'seconds');break;}if(status.group==='failed'){thrownewError(`Address alias transaction failed: ${status.code}`);}}catch(error){if(error.message.includes('failed:')){throwerror;}console.log(' Transaction status: unknown');}}// Retrieve the namespace to verify the aliasconstnamespacePath=`/namespaces/${namespaceId.toString(16)}`;console.log('Fetching namespace information from',namespacePath);constnamespaceResponse=awaitfetch(`${NODE_URL}${namespacePath}`);constnamespaceJSON=awaitnamespaceResponse.json();constnamespaceInfo=namespaceJSON.namespace;console.log('Alias information:');console.log(' Alias type:',namespaceInfo.alias.type);if(namespaceInfo.alias.type===2){// ADDRESS typeconstaliasedAddress=newmodels.Address(Uint8Array.from(Buffer.from(namespaceInfo.alias.address,'hex')));console.log(' Linked address:',aliasedAddress.toString());}// Send a transfer using the alias instead of a raw addressconsole.log('Using alias in transfer:',namespaceName);// Encode the namespace ID as a recipient address (24 bytes)// Byte 0: network byte (Network Identifier | 0x01 to indicate alias)// Bytes 1-8: namespace ID in little-endian// Bytes 9-23: zero paddingconstrecipientPath=generateNamespacePath(namespaceName);constrecipientId=recipientPath[recipientPath.length-1];constrecipientBytes=newUint8Array(24);recipientBytes[0]=facade.network.identifier|0x01;// Convert namespace ID to little-endian bytesconstrecipientIdBytes=newUint8Array(8);for(leti=0;i<8;i++){recipientIdBytes[i]=Number((recipientId>>BigInt(i*8))&0xFFn);}recipientBytes.set(recipientIdBytes,1);// Bytes 9-23 are already zero-filledconstrecipientAddress=newSymbolFacade.Address(recipientBytes);consttransferTx=facade.transactionFactory.create({type:'transfer_transaction_v1',signerPublicKey:signerKeyPair.publicKey.toString(),deadline:timestamp.addHours(2).timestamp,recipientAddress:recipientAddress,mosaics:[{mosaicId:generateMosaicAliasId('symbol.xym'),amount:1_000_000n// 1 XYM}]});console.log('Transfer transaction:');console.log(' Recipient address (alias):',recipientAddress.toString());}catch(e){console.error(e.message);}
The snippet reads the signer's private key from the SIGNER_PRIVATE_KEY environment variable, which defaults to a
test key if not set.
The signer's address is derived from the public key.
This account must own the namespace being linked.
namespace_name=os.getenv('NAMESPACE_NAME','my_namespace')print(f'Namespace name: {namespace_name}')namespace_id=generate_namespace_path(namespace_name)[-1]print(f'Namespace ID: {namespace_id} ({hex(namespace_id)})')# Target address to link the namespace totarget_address=Address(os.getenv('TARGET_ADDRESS','TCWYXKVYBMO4NBCUF3AXKJMXCGVSYQOS7ZG2TLI'))print(f'Target address: {target_address}')
constnamespaceName=process.env.NAMESPACE_NAME||'my_namespace';console.log('Namespace name:',namespaceName);constnsPath=generateNamespacePath(namespaceName);constnamespaceId=nsPath[nsPath.length-1];console.log('Namespace ID:',`${namespaceId} (0x${namespaceId.toString(16)})`);// Target address to link the namespace toconsttargetAddress=newSymbolFacade.Address(process.env.TARGET_ADDRESS||'TCWYXKVYBMO4NBCUF3AXKJMXCGVSYQOS7ZG2TLI');console.log('Target address:',targetAddress.toString());
The code defines:
Namespace name: The namespace to link, read from the NAMESPACE_NAME environment variable,
which defaults to my_namespace if not set.
This name must match a namespace that your account already owns.
Namespace ID: The ID is generated from the namespace name using ,
which returns an array of IDs for each level in the hierarchy.
The last element is selected to get the final namespace ID.
Taking the last element works for both root namespaces and subnamespaces.
For a root namespace like foo, the array contains one element.
For a subnamespace like symbol.xym, it contains two elements, and the last one is the ID of xym under symbol.
Subnamespace IDs are unique
Subnamespace IDs are derived hierarchically, so two subnamespaces with the same leaf name but different parents
produce different IDs.
For example, the last element of the path for foo.xym and bar.xym will be different.
Target address: The address that the namespace will point to, read from the TARGET_ADDRESS
environment variable. If not set, a default test address is used.
# Fetch current network timetime_path='/node/time'print(f'Fetching current network time from {time_path}')withurllib.request.urlopen(f'{NODE_URL}{time_path}')asresponse:response_json=json.loads(response.read().decode())receive_timestamp=(response_json['communicationTimestamps']['receiveTimestamp'])timestamp=NetworkTimestamp(int(receive_timestamp))print(f' Network time: {timestamp.timestamp} ms since nemesis')# Fetch recommended feesfee_path='/network/fees/transaction'print(f'Fetching recommended fees from {fee_path}')withurllib.request.urlopen(f'{NODE_URL}{fee_path}')asresponse:response_json=json.loads(response.read().decode())median_mult=response_json['medianFeeMultiplier']minimum_mult=response_json['minFeeMultiplier']fee_mult=max(median_mult,minimum_mult)print(f' Fee multiplier: {fee_mult}')
# Build the alias transactiontransaction=facade.transaction_factory.create({'type':'address_alias_transaction_v1','signer_public_key':signer_key_pair.public_key,'deadline':timestamp.add_hours(2).timestamp,'namespace_id':namespace_id,'address':target_address,'alias_action':'link'})transaction.fee=Amount(fee_mult*transaction.size)
// Build the alias transactionconsttransaction=facade.transactionFactory.create({type:'address_alias_transaction_v1',signerPublicKey:signerKeyPair.publicKey.toString(),deadline:timestamp.addHours(2).timestamp,namespaceId:namespaceId,address:targetAddress,aliasAction:'link'});transaction.fee=newmodels.Amount(feeMult*transaction.size);
The address alias transaction specifies:
Type: Address alias transactions use the type address_alias_transaction_v1.
Signer public key: The account that owns the namespace and will pay the transaction fee.
Namespace ID: The identifier of the namespace being linked.
Address: The target address to link to the namespace.
Alias action: The value link creates the alias. To remove the alias later, use unlink instead.
Unlinking an alias
To unlink a namespace from an address, announce another address_alias_transaction_v1 transaction with the same
namespace ID and address, but set the alias_action field to unlink.
The unlinking process does not remove the namespace itself, only the association between the namespace and the
address.
After unlinking, the namespace can be linked to a different address or mosaic.
# Sign transaction and generate final payloadsignature=facade.sign_transaction(signer_key_pair,transaction)json_payload=facade.transaction_factory.attach_signature(transaction,signature)print('Built transaction:')print(json.dumps(transaction.to_json(),indent=2))transaction_hash=facade.hash_transaction(transaction)print(f'Transaction hash: {transaction_hash}')# Announce transactionprint('Announcing address alias transaction to /transactions')request=urllib.request.Request(f'{NODE_URL}/transactions',data=json_payload.encode(),headers={'Content-Type':'application/json'},method='PUT')withurllib.request.urlopen(request)asresponse:print(f' Response: {response.read().decode()}')
// Sign transaction and generate final payloadconstsignature=facade.signTransaction(signerKeyPair,transaction);constjsonPayload=facade.transactionFactory.static.attachSignature(transaction,signature);console.log('Built transaction:');console.dir(transaction.toJson(),{colors:true});consttransactionHash=facade.hashTransaction(transaction).toString();console.log('Transaction hash:',transactionHash);// Announce transactionconsole.log('Announcing address alias transaction to /transactions');constannounceResponse=awaitfetch(`${NODE_URL}/transactions`,{method:'PUT',headers:{'Content-Type':'application/json'},body:jsonPayload});console.log(' Response:',awaitannounceResponse.text());
# Wait for confirmationprint('Waiting for transaction confirmation...')forattemptinrange(60):time.sleep(1)try:status_url=(f'{NODE_URL}/transactionStatus/{transaction_hash}')withurllib.request.urlopen(status_url)asresponse:status=json.loads(response.read().decode())print(f' Transaction status: {status["group"]}')ifstatus['group']=='confirmed':print('Address alias transaction confirmed in',attempt,'seconds')breakifstatus['group']=='failed':raiseException('Address alias transaction failed:',status['code'])excepturllib.error.HTTPError:print(' Transaction status: unknown')
# Retrieve the namespace to verify the aliasnamespace_path=f'/namespaces/{namespace_id:x}'print(f'Fetching namespace information from {namespace_path}')withurllib.request.urlopen(f'{NODE_URL}{namespace_path}')asresponse:response_json=json.loads(response.read().decode())namespace_info=response_json['namespace']print('Alias information:')alias_type=namespace_info['alias']['type']print(f' Alias type: {alias_type}')ifalias_type==2:# ADDRESS typealiased_address_hex=namespace_info['alias']['address']aliased_address=Address(bytes.fromhex(aliased_address_hex))print(f' Linked address: {aliased_address}')
// Retrieve the namespace to verify the aliasconstnamespacePath=`/namespaces/${namespaceId.toString(16)}`;console.log('Fetching namespace information from',namespacePath);constnamespaceResponse=awaitfetch(`${NODE_URL}${namespacePath}`);constnamespaceJSON=awaitnamespaceResponse.json();constnamespaceInfo=namespaceJSON.namespace;console.log('Alias information:');console.log(' Alias type:',namespaceInfo.alias.type);if(namespaceInfo.alias.type===2){// ADDRESS typeconstaliasedAddress=newmodels.Address(Uint8Array.from(Buffer.from(namespaceInfo.alias.address,'hex')));console.log(' Linked address:',aliasedAddress.toString());}
To verify the alias was created, the code retrieves the namespace information from the network
using the /namespaces/{namespaceId}GET endpoint.
The response includes the alias type (address) and the linked address, confirming the namespace now points to the
specified address.
# Send a transfer using the alias instead of a raw addressprint(f'Using alias in transfer: {namespace_name}')# Encode the namespace ID as a recipient address (24 bytes)# Byte 0: network byte (Network Identifier | 0x01 to indicate alias)# Bytes 1-8: namespace ID in little-endian# Bytes 9-23: zero paddingrecipient_id=generate_namespace_path(namespace_name)[-1]recipient_address=Address(bytes([facade.network.identifier|0x01])+recipient_id.to_bytes(8,'little')+bytes(15))transfer_tx=facade.transaction_factory.create({'type':'transfer_transaction_v1','signer_public_key':signer_key_pair.public_key,'deadline':timestamp.add_hours(2).timestamp,'recipient_address':recipient_address,'mosaics':[{'mosaic_id':generate_mosaic_alias_id('symbol.xym'),'amount':1_000_000# 1 XYM}]})print('Transfer transaction:')print(f' Recipient address (alias): {recipient_address}')
// Send a transfer using the alias instead of a raw addressconsole.log('Using alias in transfer:',namespaceName);// Encode the namespace ID as a recipient address (24 bytes)// Byte 0: network byte (Network Identifier | 0x01 to indicate alias)// Bytes 1-8: namespace ID in little-endian// Bytes 9-23: zero paddingconstrecipientPath=generateNamespacePath(namespaceName);constrecipientId=recipientPath[recipientPath.length-1];constrecipientBytes=newUint8Array(24);recipientBytes[0]=facade.network.identifier|0x01;// Convert namespace ID to little-endian bytesconstrecipientIdBytes=newUint8Array(8);for(leti=0;i<8;i++){recipientIdBytes[i]=Number((recipientId>>BigInt(i*8))&0xFFn);}recipientBytes.set(recipientIdBytes,1);// Bytes 9-23 are already zero-filledconstrecipientAddress=newSymbolFacade.Address(recipientBytes);consttransferTx=facade.transactionFactory.create({type:'transfer_transaction_v1',signerPublicKey:signerKeyPair.publicKey.toString(),deadline:timestamp.addHours(2).timestamp,recipientAddress:recipientAddress,mosaics:[{mosaicId:generateMosaicAliasId('symbol.xym'),amount:1_000_000n// 1 XYM}]});console.log('Transfer transaction:');console.log(' Recipient address (alias):',recipientAddress.toString());
Once the namespace is linked to an address, the namespace can be used in place of the address in transactions.
The code demonstrates creating a transfer transaction using the alias as the recipient address instead of
the full hexadecimal address.
For simplicity, this example creates the transaction but does not announce it or wait for its confirmation.
To use a namespace as a recipient address, the namespace ID must be encoded into a 24-byte address.
The namespace ID is obtained using the last component, as described in the
previous section.
At this level, the SDK does not expose a dedicated helper for this operation, so the encoding is done manually
with the following structure:
Byte 0: Network byte with alias flag set (network_identifier | 0x01)
Bytes 1-8: Namespace ID in little-endian byte order
Bytes 9-23: Zero padding
For more details on how to announce transfer transactions, see the
Transfer Transaction tutorial.
Address Resolution Receipt
When the network processes a transaction that uses a namespace alias as a recipient address, it generates an
Address Resolution Receipt.
This receipt records the actual address the alias pointed to at the time the transaction was confirmed.
This is important for historical auditability: since aliases can be changed or removed at any time, the receipt
ensures that the resolved address can always be verified, even if the alias has since been updated.
Using node https://reference.symboltest.net:3001
Signer address: TCHBDENCLKEBILBPWP3JPB2XNY64OE7PYHHE32I
Namespace name: nsaddr_1770541301
Namespace ID: 12901002700615428842 (0xb309919a9089aaea)
Target address: TCWYXKVYBMO4NBCUF3AXKJMXCGVSYQOS7ZG2TLI
Fetching current network time from /node/time
Network time: 103291999249 ms since nemesis
Fetching recommended fees from /network/fees/transaction
Fee multiplier: 100
Built transaction:
{
"signature": "88D2148FB1938012BE845D221363768ECBE903032940F37E7227728FD655B73D02B1A78E03F23C25E8F6F1B746C61E8BE3623C5D5F1E5D57BEBBA9A7F56B6604",
"signer_public_key": "3B6A27BCCEB6A42D62A3A8D02A6F0D73653215771DE243A63AC048A18B59DA29",
"version": 1,
"network": 152,
"type": 16974,
"fee": "16100",
"deadline": "103299199249",
"namespace_id": "12901002700615428842",
"address": "98AD8BAAB80B1DC684542EC175259711AB2C41D2FE4DA9AD",
"alias_action": 1
}
Transaction hash: 8312500644961DA08EF4899AE5160C2B810A8B506B74C58D3F4FCF257C309827
Announcing address alias transaction to /transactions
Response: {"message":"packet 9 was pushed to the network via /transactions"}
Waiting for transaction confirmation...
Transaction status: unconfirmed
Transaction status: confirmed
Address alias transaction confirmed in 17 seconds
Fetching namespace information from /namespaces/b309919a9089aaea
Alias information:
Alias type: 2
Linked address: TCWYXKVYBMO4NBCUF3AXKJMXCGVSYQOS7ZG2TLI
Using alias in transfer: nsaddr_1770541301
Transfer transaction:
Recipient address (alias): THVKVCMQTKIQTMYAAAAAAAAAAAAAAAAAAAAAAAA
Some highlights from the output:
Namespace and target (lines 3, 5): The namespace nsaddr_1770541301 is being linked to the target address
TCWYXKVYBMO4NBCUF3AXKJMXCGVSYQOS7ZG2TLI.
Transaction hash (line 23): The transaction hash can be used to search for the transaction in the
Symbol Testnet Explorer.
Alias verification (lines 32-33): The namespace information confirms the alias type is 2 (address) and
shows the linked address.
Using the alias (line 36): A transfer transaction is created using the alias as the recipient,
demonstrating that it can be used in place of the full address.
Different recipient address
The recipient address differs from the target address because it is the
encoded namespace ID, not the target address itself.
The network resolves the alias to the linked address when processing the transaction.