Every time a transaction uses an alias instead of a raw address or mosaic ID, the network stores a receipt
with the actual value the alias pointed to at confirmation time.
The type of receipt that captures namespace resolutions is called a
resolution statement.
This tutorial shows how to query resolution statements to find the real address and mosaic ID behind a namespace
alias used in a confirmed transaction.
# Hash of a confirmed tx that used a namespace aliasTX_HASH=os.getenv('TRANSACTION_HASH','BA0C65DB752A3BF1B25285540642537ECE8C2CA716577EDF8BF0F8597A85ADC4')print(f'Transaction hash: {TX_HASH}')
// Hash of a confirmed tx that used a namespace aliasconstTX_HASH=process.env.TRANSACTION_HASH||'BA0C65DB752A3BF1B25285540642537ECE8C2CA716577EDF8BF0F8597A85ADC4';console.log('Transaction hash:',TX_HASH);
The code defines the hash of a confirmed transaction that used namespace aliases instead of a plain address and
mosaic ID.
This hash is read from the TRANSACTION_HASH environment variable, which defaults to a known transaction on the
Symbol testnet.
The provided default transaction hash might result in a Not Found error if the testnet is reset.
You can use TRANSACTION_HASH to analyze a different transaction.
The response includes a meta object with the blockheight where the transaction was confirmed.
This height is needed to query the resolution statements for that specific block.
The transaction metadata also includes the index field, which is the 0-based position of the transaction within
the block.
The code converts it to a 1-based primaryId (index + 1) to match against the resolution entries later.
constrecipientHex=txData.transaction.recipientAddress;constrecipientBytes=Buffer.from(recipientHex,'hex');constisAddressAlias=(recipientBytes[0]&0x01)===1;console.log(' Recipient:',recipientHex);console.log(' Is address alias:',isAddressAlias);
The retrieved transaction contains the recipientAddress field.
If the transaction used a namespace alias as recipient, this field holds the unresolved value (the encoded
namespace ID) instead of a real address.
The code checks whether the recipient is an alias by inspecting the lowest bit of the first byte:
constaliasedMosaics=newSet();constmosaics=txData.transaction.mosaics;for(constmosaicofmosaics){constmosaicId=BigInt(`0x${mosaic.id}`);constisMosaicAlias=(mosaicId>>63n&1n)===1n;if(isMosaicAlias)aliasedMosaics.add(mosaic.id);console.log(` Mosaic: ${mosaic.id}`);console.log(` Is mosaic alias: ${isMosaicAlias}`);}
The code iterates through the transaction's mosaics array and checks whether each mosaic ID is a namespace alias
by inspecting bit 63 (the highest bit) of its 64-bit value:
If the bit is 1, the value is a namespace ID used as a mosaic alias, as described in the
Linking Namespaces to Mosaics tutorial.
If the bit is 0, the value is a regular mosaic ID and no resolution is needed.
ifis_address_alias:address_path=('/statements/resolutions/address'f'?height={block_height}')print(f'\nFetching address resolutions from {address_path}')withurllib.request.urlopen(f'{NODE_URL}{address_path}')asresponse:address_data=json.loads(response.read().decode())address_statements=address_data['data']print(f' Found {len(address_statements)}'+' resolution statement(s)')
if(isAddressAlias){constaddressPath='/statements/resolutions/address'+`?height=${blockHeight}`;console.log('\nFetching address resolutions from',addressPath);constaddressResponse=awaitfetch(`${NODE_URL}${addressPath}`);constaddressData=awaitaddressResponse.json();constaddressStatements=addressData.data;console.log(` Found ${addressStatements.length}`+' resolution statement(s)');
Using the block height from the transaction metadata, the code queries the
/statements/resolutions/addressGET endpoint to retrieve the address resolution statements for that block.
Each resolution statement contains:
Height: The block where the resolution occurred.
Unresolved: The namespace alias (encoded as an address) that was used in the transaction.
Resolution entries: An array mapping the alias to the actual address at the time of confirmation.
The endpoint returns all address resolution statements for the block.
The code skips any statement whose unresolved field does not match the transaction's recipientAddress,
since a single block can contain multiple resolution statements if different namespace aliases were used.
Each statement can also have multiple entries if the alias was re-linked to a different value between transactions
in the same block.
If consecutive transactions resolve to the same value, only a single entry is stored.
Each resolution entry contains:
Source: Indicates from which transaction the resolved value applies, using a primaryId
(1-based index of the transaction in the block) and secondaryId
(1-based index within an aggregate transaction, or 0 for standalone transactions).
Resolved: The actual address the alias pointed to from the indicated source onward.
To determine the resolved value for the analyzed transaction, the code finds the last entry whose primaryId is
less than or equal to the transaction's primaryId.
This is the value the network used for that specific transaction, regardless of what the alias currently points to,
even if the alias was defined multiple times in the same block.
The same transaction also used symbol.xym as a mosaic alias instead of a raw mosaic ID.
The code queries the /statements/resolutions/mosaicGET endpoint with the same block height to retrieve
the mosaic resolution statements.
As with the address resolution, the code skips statements whose unresolved field does not match the aliased
mosaic IDs from the transaction.
The response follows the same structure as the address resolution, but the resolved field contains a
mosaic ID instead of an address.
The same matching logic applies: the last entry whose primaryId is less than or equal to the transaction's
primaryId gives the resolved mosaic ID.
Using node https://reference.symboltest.net:3001
Transaction hash: BA0C65DB752A3BF1B25285540642537ECE8C2CA716577EDF8BF0F8597A85ADC4
Fetching transaction from /transactions/confirmed/BA0C65DB752A3BF1B25285540642537ECE8C2CA716577EDF8BF0F8597A85ADC4
Block height: 3125903
Transaction index: 0 (primaryId: 1)
Recipient: 99EC0888813BE133E6000000000000000000000000000000
Is address alias: True
Mosaic: E74B99BA41F4AFEE
Is mosaic alias: True
Fetching address resolutions from /statements/resolutions/address?height=3125903
Found 1 resolution statement(s)
Address resolution:
Unresolved: 99EC0888813BE133E6000000000000000000000000000000
Resolved: TCWYXKVYBMO4NBCUF3AXKJMXCGVSYQOS7ZG2TLI
Fetching mosaic resolutions from /statements/resolutions/mosaic?height=3125903
Found 1 resolution statement(s)
Mosaic resolution:
Unresolved: E74B99BA41F4AFEE
Resolved: 72C0212E67A08BCE
Some highlights from the output:
Transaction hash (line 2): The hash of the confirmed transaction being analyzed.
Block height (line 4): The block where the transaction was confirmed, used to query resolution statements.
Transaction index (line 5): The 0-based position of the transaction in the block, converted to a 1-based
primaryId for matching against resolution entries.
Recipient and alias checks (lines 6-9): The recipient field contains the encoded namespace alias, and the alias
flag check confirms it is a namespace alias rather than a regular address.
The mosaic alias check confirms that E74B99BA41F4AFEE is also a namespace alias.
Resolved address (lines 15-16): The address resolution shows that the namespace alias resolved to
TCWYXKVYBMO4NBCUF3AXKJMXCGVSYQOS7ZG2TLI for this transaction.
Resolved mosaic ID (lines 22-23): The mosaic resolution shows that the unresolved namespace ID
E74B99BA41F4AFEE resolved to mosaic ID 72C0212E67A08BCE for this transaction.
Resolution statements only contain numeric IDs
Resolution statements contain mosaic IDs, not human-readable names like symbol.xym.
To retrieve the readable name from an ID, use /namespaces/namesPOST.