Mosaics represent assets on the Symbol blockchain, such as currencies, collectibles, or access rights.
Unlike tokens on other platforms, Symbol mosaics are supported directly at the protocol level
and require no additional coding to use.
Their properties are configurable to support various use cases, from simple currencies to restricted tokens.
This tutorial shows how to create a mosaic and mint its initial supply.
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 will own the created mosaic.
# 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}')
The mosaic definition transaction registers a new mosaic on the network with the following properties:
Type: Mosaic definition transactions use the type mosaic_definition_transaction_v1.
Duration: The number of blocks the mosaic will remain active. A value of 0 means the mosaic never expires.
If a duration is provided, the maximum allowed value is
approximately 10 years (3,650 days or approximately 10,512,000 blocks
with the default 30-second block target).
Expiring mosaics become unusable
When an expiring mosaic reaches its duration, it can no longer be transferred or used in transactions.
Balances remain in accounts but are effectively frozen.
Before setting a duration, consider whether your use case truly requires it.
Divisibility: The number of decimal places the mosaic supports.
For example, a value of 2 means each whole unit can be divided into 100 (102) atomic units.
For more details, see Divisibility in the Textbook.
Nonce: An arbitrary 32-bit unsigned integer (0 to 4,294,967,295) that acts as a locally unique identifier
for mosaics created by the same account.
The mosaic ID is derived deterministically from the owner's address and the nonce using
, so each unique nonce produces a different mosaic.
Nonce choice in this tutorial
This tutorial uses the current timestamp as the nonce to ensure each run creates a unique mosaic.
The & 0xFFFFFFFF bitmask truncates the value to fit in 32 bits.
In practice, any value works as long as the same account has not already used that nonce.
Flags: A space-separated set of behavior restrictions for the mosaic.
Multiple flags can be combined in a single string, for example 'transferable restrictable'.
The available flags are:
transferable: the mosaic can be freely sent between any accounts.
supply_mutable: the total supply can be changed after creation.
restrictable: the owner can apply
mosaic restrictions to control which accounts
can hold or transfer the mosaic.
revokable: the creator can reclaim units from any account.
In this example, transferable restrictable is used.
Lease fee
In addition to the standard transaction fee,
creating a mosaic requires a one-time lease fee paid in XYM.
Unlike the transaction fee, the lease fee is not included in the transaction request.
It is deducted automatically by the network from the signer's account
when the mosaic definition transaction is confirmed.
The amount of the lease fee can be queried from the /network/fees/rentalGET endpoint
(effectiveMosaicRentalFee property).
# Sign and generate final payloadsignature=facade.sign_transaction(signer_key_pair,definition_tx)json_payload=facade.transaction_factory.attach_signature(definition_tx,signature)print('Built mosaic definition transaction:')print(json.dumps(definition_tx.to_json(),indent=2))# Announce and wait for confirmationdefinition_hash=facade.hash_transaction(definition_tx)print(f'Transaction hash: {definition_hash}')announce_transaction(json_payload,'mosaic definition')wait_for_confirmation(definition_hash,'mosaic definition')
// Sign and generate final payloadconstdefSignature=facade.signTransaction(signerKeyPair,definitionTx);constdefPayload=facade.transactionFactory.static.attachSignature(definitionTx,defSignature);console.log('Built mosaic definition transaction:');console.dir(definitionTx.toJson(),{colors:true});// Announce and wait for confirmationconstdefinitionHash=facade.hashTransaction(definitionTx).toString();console.log('Transaction hash:',definitionHash);awaitannounceTransaction(defPayload,'mosaic definition');awaitwaitForConfirmation(definitionHash,'mosaic definition');
// Sign and generate final payloadconstsupSignature=facade.signTransaction(signerKeyPair,supplyTx);constsupPayload=facade.transactionFactory.static.attachSignature(supplyTx,supSignature);console.log('Built mosaic supply change transaction:');console.dir(supplyTx.toJson(),{colors:true});// Announce and wait for confirmationconstsupplyHash=facade.hashTransaction(supplyTx).toString();console.log('Transaction hash:',supplyHash);awaitannounceTransaction(supPayload,'mosaic supply change');awaitwaitForConfirmation(supplyHash,'mosaic supply change');
The mosaic supply change transaction is signed and announced following the same process as the mosaic definition
transaction.
Combining both transactions
Instead of announcing the definition and supply change as two separate transactions, you can submit them
together in a single Complete Aggregate Transaction.
This ensures both operations are confirmed atomically in the same block.
Even without the supply_mutable flag, supply changes are allowed as long as the owner holds the entire supply.
Once any units are distributed to other accounts, the supply becomes permanently fixed.
To verify the mosaic was created successfully, the code retrieves it from the network
using the /mosaics/{mosaicId}GET endpoint and displays its properties.
A successful response confirms the mosaic exists on the network with the expected supply and divisibility.
Using node https://reference.symboltest.net:3001
Signer address: TCHBDENCLKEBILBPWP3JPB2XNY64OE7PYHHE32I
Fetching current network time from /node/time
Network time: 103504012049 ms since nemesis
Fetching recommended fees from /network/fees/transaction
Fee multiplier: 100
--- Creating mosaic definition ---
Mosaic nonce: 1770754477
Mosaic ID: 8318126551268698739 (0x736fec06ed1daa73)
Built mosaic definition transaction:
{
"signature": "6516FB17F162075795E8A4578595DE4745A57B151A6A6ACABF613C1ADF94DC36AF13F661E9FC356723A1F653D2ECC434E514F891A7D16502825431FE5AC17F06",
"signer_public_key": "3B6A27BCCEB6A42D62A3A8D02A6F0D73653215771DE243A63AC048A18B59DA29",
"version": 1,
"network": 152,
"type": 16717,
"fee": "15000",
"deadline": "103511212049",
"id": "8318126551268698739",
"duration": "0",
"nonce": 1770754477,
"flags": 6,
"divisibility": 2
}
Transaction hash: 959C4FDE753700E21959CB23E46EE761937A3AFEAFB40DBD9ADFBEE2D1C85F8B
Announcing mosaic definition to /transactions
Response: {"message":"packet 9 was pushed to the network via /transactions"}
Waiting for mosaic definition confirmation...
Transaction status: unconfirmed
Transaction status: unconfirmed
Transaction status: confirmed
Mosaic definition confirmed in 12 seconds
--- Increasing mosaic supply ---
Built mosaic supply change transaction:
{
"signature": "9704D30D6B060CB28A5A8DA3BAC40B7D02D878199C32D57FA70B6EB213735677BF7380F14A1A9B04B7DEA806D55A379CF20BAC3BDA24D16094DF2F97917A5605",
"signer_public_key": "3B6A27BCCEB6A42D62A3A8D02A6F0D73653215771DE243A63AC048A18B59DA29",
"version": 1,
"network": 152,
"type": 16973,
"fee": "14500",
"deadline": "103511212049",
"mosaic_id": "8318126551268698739",
"delta": "10000",
"action": 1
}
Transaction hash: E4E002C9E4536666E47E4B98DB7307FF5715C4BD8C4579D8AD67C9CBCECC2CD2
Announcing mosaic supply change to /transactions
Response: {"message":"packet 9 was pushed to the network via /transactions"}
Waiting for mosaic supply change confirmation...
Transaction status: unconfirmed
Transaction status: confirmed
Mosaic supply change confirmed in 9 seconds
--- Verifying mosaic ---
Fetching mosaic information from /mosaics/736fec06ed1daa73
Mosaic information:
Mosaic ID: 736FEC06ED1DAA73
Supply: 10000
Flags: 6
Divisibility: 2
Duration: 0
Some highlights from the output:
Mosaic ID (line 10): The nonce is combined with the signer's address
to derive the mosaic ID 0x736fec06ed1daa73.
Fee (line 18): The transaction fee of 0.015 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.
Mosaic ID (line 20): The id field is automatically computed by the transaction factory from the nonce
and the signer's address, matching the value printed on line 10.
Mosaic properties (lines 21, 23-24): Flags are stored as a bitmask, where each flag occupies a single bit:
supply_mutable (1), transferable (2), restrictable (4), and revokable (8).
The value 6 equals transferable (2) + restrictable (4).
The divisibility is 2 and the duration 0 means the mosaic never expires.
Supply delta (line 46): The delta of 10000 atomic units represents 100.00 whole units
given the mosaic's divisibility of 2.
Verified properties (lines 60-64): The mosaic is retrieved from the network, confirming
the expected supply, flags, divisibility, and duration.
The transaction hashes printed in the output can be used to search for the transactions
in the Symbol Testnet Explorer.