Creating a mosaic

Tokenize an asset using mosaics.

Background

A private company, ComfyClothingCompany, decides that it wants to go public. Instead of a traditional IPO, the company decides to do an STO to issue tokens through the NEM platform.

In this guide, we are going to help this company to create the tokens for their STO using mosaics built-in feature and the NEM2-SDK.

Prerequisites

Getting into some code

  1. Before starting this guide, make sure you have an account loaded with cat.currency.
  2. Then, the company must create a mosaic to represent shares to their company. To do so, you will have to create a new file and define two transactions:
  1. A MosaicDefinitionTransaction to set the mosaic properties. In this example, we are going to create a mosaic configured as:
Property Value Description
Divisibility 0 Although brokerages and investment firms can fractionalize shares, the traditional minimum number of shares an investor can purchase from the open market is 1.
Duration 0 Shares of the company should exist as long as the company is in business. The ComfyClothingCompany sets this property to 0, creating a non-expiring mosaic.
Supply mutable True ComfyClothingCompany sets the initial supply of the mosaic to a typical startup amount of 10,000,000 authorized shares. As the company grows, it could choose to increase the number of shares, so the supply mutable is set to true.
Transferable True Once the initial shares are distributed, the shares will be on the market to be traded in public. Thus, the transferability property needs to be set to true.
Restrictable True Since STOs are regulated, the mosaic owner should be able to restrict which accounts can transact with the mosaic.
const privateKey = process.env.PRIVATE_KEY as string;
const account = Account.createFromPrivateKey(privateKey, NetworkType.MIJIN_TEST);

const nonce = MosaicNonce.createRandom();
const mosaicDefinitionTransaction = MosaicDefinitionTransaction.create(
    Deadline.create(),
    nonce,
    MosaicId.createFromNonce(nonce, account.publicAccount),
    MosaicFlags.create(true, true, true),
    0,
    UInt64.fromUint(0),
    NetworkType.MIJIN_TEST);
const privateKey = process.env.PRIVATE_KEY;
const account = Account.createFromPrivateKey(privateKey, NetworkType.MIJIN_TEST);

const nonce = MosaicNonce.createRandom();
const mosaicDefinitionTransaction = MosaicDefinitionTransaction.create(
    Deadline.create(),
    nonce,
    MosaicId.createFromNonce(nonce, account.publicAccount),
    MosaicFlags.create(true, true, true),
    0,
    UInt64.fromUint(0),
    NetworkType.MIJIN_TEST);
  1. A MosaicSupplyChangeTransaction, to set the initial supply. We are going to create 1,000,000 mosaic units.
const mosaicSupplyChangeTransaction = MosaicSupplyChangeTransaction.create(
    Deadline.create(),
    mosaicDefinitionTransaction.mosaicId,
    MosaicSupplyChangeAction.Increase,
    UInt64.fromUint(1000000),
    NetworkType.MIJIN_TEST);
const mosaicSupplyChangeTransaction = MosaicSupplyChangeTransaction.create(
    Deadline.create(),
    mosaicDefinitionTransaction.mosaicId,
    MosaicSupplyChangeAction.Increase,
    UInt64.fromUint(1000000),
    NetworkType.MIJIN_TEST);

Note

NEM works with absolute amounts. To get an absolute amount, multiply the amount of assets you want to create by 10divisibility. For example, if the mosaic has divisibility 2, to create 10 units (relative) you should define 1000 (absolute) instead.

  1. Announce both transactions together using an AggregateTransaction.

Note

To make the transaction only valid for your network, include the first block generation hash. Open http://localhost:3000/block/1 in a new tab and copy the meta.generationHash value.

const aggregateTransaction = AggregateTransaction.createComplete(
    Deadline.create(),
    [
        mosaicDefinitionTransaction.toAggregate(account.publicAccount),
        mosaicSupplyChangeTransaction.toAggregate(account.publicAccount)
    ],
    NetworkType.MIJIN_TEST,
    []);

const networkGenerationHash = process.env.NETWORK_GENERATION_HASH as string;
const signedTransaction = account.sign(aggregateTransaction, networkGenerationHash);

const transactionHttp = new TransactionHttp('http://localhost:3000');
transactionHttp
    .announce(signedTransaction)
    .subscribe(x=> console.log(x),err => console.error(err));
const aggregateTransaction = AggregateTransaction.createComplete(
    Deadline.create(),
    [
        mosaicDefinitionTransaction.toAggregate(account.publicAccount),
        mosaicSupplyChangeTransaction.toAggregate(account.publicAccount)
    ],
    NetworkType.MIJIN_TEST,
    []);

const networkGenerationHash = process.env.NETWORK_GENERATION_HASH;
const signedTransaction = account.sign(aggregateTransaction, networkGenerationHash);

const transactionHttp = new TransactionHttp('http://localhost:3000');
transactionHttp
    .announce(signedTransaction)
    .subscribe(x=> console.log(x),err => console.error(err));
nem2-cli transaction mosaic --amount 1000000 --divisibility 0 --non-expiring --transferable --supply-mutable --restrictable

Once the transaction gets confirmed, you can try to transfer one unit of the created mosaic to another account, modify the mosaic properties or link a namespace to the mosaic.