Skip to main content

Application Architecture

The track-and-trace application uses the IOTA MAM protocol to give returnable assets an ID and to track those assets in streams of transactions called MAM channels.


Running an open source project, like any human endeavor, involves uncertainty and trade-offs. We hope the architecture described below helps you to deploy similar systems, but it may include mistakes, and can’t address every situation. If you have any questions about your project, we encourage you to do your own research, seek out experts, and discuss them with the IOTA community.

This blueprint uses the following architecture whereby trackers register their ownership of returnable assets and attach proof of this ownership to a MAM channel in the Tangle. Whenever new trackers receive the asset, they update the MAM channel with their own custodian ID, as well as the asset's new location and its status. This way, tracers can find out where the asset is at any time by monitoring the MAM channel.

Track and Trace

Building Blocks​

To allow trackers to create and update assets' MAM channels, we use a tracker app that does the following:

  • Create a new channel
  • Attach the asset data to the Tangle, using the new MAM channel
  • Save the asset data in the database

Creating a New Channel​

When trackers first register their ownership of an asset, the createItemChannel() method is called, which creates a new MAM channel, acting as the asset's digital twin. This MAM channel registers the following information about the asset:

assetUniqueIDThe unique ID of the asset, which is generated by the registration APIAssets could carry a QR code, which allows trackers and tracers to capture this ID by scanning the code
assetOwnerIDThe unique ID of the asset owner, which is generated by the registration API
assetCustodianIDThe unique ID of the latest tracker to update the asset's MAM channelWhen the asset is first registered, this ID is the same as the asset owner's ID
locationThe location of the assetThe location
timeThe time at which this asset information is created
statusThe current status of the assetIn the blueprint, this field can be set to in-use, returned, or lost
// create a new asset 
export const createItemChannel = (project, itemId, request, userId) => {

const messageBody = {
time: null,
location: null,
assetUniqueID: null,
assetOwnerID: null,
assetUserID: null

Before setting up the channel, we recommended setting the channel mode to restricted. This mode allows you to encrypt the data in each MAM message and to allow access only to selected trackers and tracers.

// create a new restricted channel 
const createNewChannel = async (payload, secretKey) => {
const channelState = createChannel(generateSeed(81), 2, 'restricted', secretKey)
return channelState;

Attaching the Asset Data to the Tangle​

After creating the MAM channel, we can publish the asset information to the IOTA Tangle, using the mamAttach() method.

// store new messages for each new asset and for each change of custody 
// Publish to tangle
const publish = async data => {
try {
// Create the MAM payload
const trytes = TrytesHelper.fromAscii(JSON.stringify(payload))
const mamMessage = createMessage(channelState, trytes)

// Save the new state of the MAM channel
channelState.root = mamMessage.root;

// Attach the payload
await mamAttach(node, mamMessage, "TRACKANDTRACE");
return channelState;
} catch (error) {
console.log('MAM publish error', error);
return null;

Saving the Asset Data in the Database​

To allow trackers to use the API to update the MAM channel, the assetUniqueID as well as the following information is also stored in a database.

channelRootThe root of the MAM channel, which allows the API to find it in the TangleIf the MAM channel is public, this is the address of the first transaction in the channel
channelSideKey>If the MAM channel is restricted, this field contains its side key, which allows the API to encrypt and decrypt the MAM messages

The createItem() function is used to save the necessary data in the database when the asset is created.

Track and Trace

export const createItem = (eventBody, mam) => {
const item = {

Then, when a new tracker takes custody of the asset, that tracker updates the assetCustodianID, location, time, and status fields and attaches it to the same MAM channel, using the updateItem() function to save the new asset data to the database.

export const updateItem = (eventBody, mam) => {
const item = {

Customization Considerations​

If you want to use this blueprint in your own system, you should consider the following.

Missing Assets​

You may want to implement a process to handle missing assets. For example, if an asset's MAM channel is not updated within a certain timeframe, you could trigger a message to be sent to the last known custodian.