Creating a token

Tokenize an asset using tokens.

Prerequisites

Method #01: Using the Desktop Wallet

  1. Click on the “Tokens” tab from the left side menu.

  2. Click on the “Create new tokens” tab on the top of the page.

resources/images/screenshots/desktop-create-token-1.gif

3. Determine the properties of the token you desire to create. You can read “Token Properties” to decide how do you want to configure your token. Click “Send”.

resources/images/screenshots/desktop-create-token-2.gif
  1. Verify the information on the popup and enter your wallet password. Click “Confirm”. This should send the transaction to the network.

resources/images/screenshots/desktop-create-token-3.gif
  1. When the transaction becomes confirmed, you can check to see that the token has been created by going back to the “Owned tokens” tab.

Method #02: Using the SDK

1. Open a new file and define a TokenDefinitionTransaction. This transaction defines the token properties your token will have. You can read Token Properties to decide how do you want to configure your token.

// replace with network type
const networkType = NetworkType.TEST_NET;
// replace with private key
const privateKey =
  '1111111111111111111111111111111111111111111111111111111111111111';
const account = Account.createFromPrivateKey(privateKey, networkType);
// replace with duration (in blocks)
const duration = UInt64.fromUint(0);
// replace with custom token flags
const isSupplyMutable = true;
const isTransferable = true;
const isRestrictable = true;
// replace with custom divisibility
const divisibility = 0;

const nonce = TokenNonce.createRandom();
const tokenDefinitionTransaction = TokenDefinitionTransaction.create(
  Deadline.create(epochAdjustment),
  nonce,
  TokenId.createFromNonce(nonce, account.address),
  TokenFlags.create(isSupplyMutable, isTransferable, isRestrictable),
  divisibility,
  duration,
  networkType,
);
// replace with network type
const networkType = bitxor_sdk_1.NetworkType.TEST_NET;
// replace with private key
const privateKey =
  '1111111111111111111111111111111111111111111111111111111111111111';
const account = bitxor_sdk_1.Account.createFromPrivateKey(
  privateKey,
  networkType,
);
// replace with duration (in blocks)
const duration = bitxor_sdk_1.UInt64.fromUint(0);
// replace with custom token flags
const isSupplyMutable = true;
const isTransferable = true;
const isRestrictable = true;
// replace with custom divisibility
const divisibility = 0;
const nonce = bitxor_sdk_1.TokenNonce.createRandom();
const tokenDefinitionTransaction = bitxor_sdk_1.TokenDefinitionTransaction.create(
  bitxor_sdk_1.Deadline.create(epochAdjustment),
  nonce,
  bitxor_sdk_1.TokenId.createFromNonce(nonce, account.address),
  bitxor_sdk_1.TokenFlags.create(
    isSupplyMutable,
    isTransferable,
    isRestrictable,
  ),
  divisibility,
  duration,
  networkType,
);
        // replace with node endpoint
        try (final RepositoryFactory repositoryFactory = new RepositoryFactoryVertxImpl(
                "NODE_URL")) {
            final NetworkType networkType = repositoryFactory.getNetworkType().toFuture().get();
            // replace with private key
            final String privateKey = "1111111111111111111111111111111111111111111111111111111111111111";
            final Account account = Account
                    .createFromPrivateKey(privateKey, networkType);
            // replace with duration (in blocks)
            final BlockDuration duration = new BlockDuration(10);
            // replace with custom token flags
            final boolean isSupplyMutable = true;
            final boolean isTransferable = true;
            final boolean isRestrictable = true;
            // replace with custom divisibility
            final int divisibility = 0;

            final TokenNonce nonce = TokenNonce.createRandom();

            final TokenDefinitionTransaction tokenDefinitionTransaction = TokenDefinitionTransactionFactory
                    .create(networkType,
                            nonce,
                            TokenId.createFromNonce(nonce, account.getPublicAccount()),
                            TokenFlags.create(isSupplyMutable, isTransferable, isRestrictable),
                            divisibility,
                            duration)
                    .build();

2. Define a TokenSupplyChangeTransaction to set the initial supply. For instance, we can set it to 1,000,000 token units.

// replace with token units to increase
const delta = 1000000;

const tokenSupplyChangeTransaction = TokenSupplyChangeTransaction.create(
  Deadline.create(epochAdjustment),
  tokenDefinitionTransaction.tokenId,
  TokenSupplyChangeAction.Increase,
  UInt64.fromUint(delta * Math.pow(10, divisibility)),
  networkType,
);
// replace with token units to increase
const delta = 1000000;
const tokenSupplyChangeTransaction = bitxor_sdk_1.TokenSupplyChangeTransaction.create(
  bitxor_sdk_1.Deadline.create(epochAdjustment),
  tokenDefinitionTransaction.tokenId,
  bitxor_sdk_1.TokenSupplyChangeAction.Increase,
  bitxor_sdk_1.UInt64.fromUint(delta * Math.pow(10, divisibility)),
  networkType,
);
            // replace with token units to increase
            final int delta = 1000000;
            final TokenSupplyChangeTransaction tokenSupplyChangeTransaction = TokenSupplyChangeTransactionFactory
                    .create(
                            networkType,
                            tokenDefinitionTransaction.getTokenId(),
                            TokenSupplyChangeActionType.INCREASE,
                            BigDecimal.valueOf(delta * Math.pow(10, divisibility)).toBigInteger())
                    .build();

Note

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

3. Announce both transactions together using an Aggregate Transaction. Include the network generation hash to make the transaction only valid for your network. Open NODE_URL /node/info in a new browser tab and copy the meta.networkGenerationHash value.

const aggregateTransaction = AggregateTransaction.createComplete(
  Deadline.create(epochAdjustment),
  [
    tokenDefinitionTransaction.toAggregate(account.publicAccount),
    tokenSupplyChangeTransaction.toAggregate(account.publicAccount),
  ],
  networkType,
  [],
  UInt64.fromUint(2000000),
);

// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
  '1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = account.sign(
  aggregateTransaction,
  networkGenerationHash,
);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();

transactionHttp.announce(signedTransaction).subscribe(
  (x) => console.log(x),
  (err) => console.error(err),
);
const aggregateTransaction = bitxor_sdk_1.AggregateTransaction.createComplete(
  bitxor_sdk_1.Deadline.create(epochAdjustment),
  [
    tokenDefinitionTransaction.toAggregate(account.publicAccount),
    tokenSupplyChangeTransaction.toAggregate(account.publicAccount),
  ],
  networkType,
  [],
  bitxor_sdk_1.UInt64.fromUint(2000000),
);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
  '1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = account.sign(
  aggregateTransaction,
  networkGenerationHash,
);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new bitxor_sdk_1.RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransaction).subscribe(
  (x) => console.log(x),
  (err) => console.error(err),
);
            final AggregateTransaction aggregateTransaction = AggregateTransactionFactory
                    .createComplete(
                            networkType,
                            Arrays.asList(
                                tokenDefinitionTransaction.toAggregate(account.getPublicAccount()),
                                tokenSupplyChangeTransaction.toAggregate(account.getPublicAccount())
                            ))
                    .maxFee(BigInteger.valueOf(2000000)).build();

            final String generationHash = repositoryFactory.getGenerationHash().toFuture().get();
            final SignedTransaction signedTransaction = account
                    .sign(aggregateTransaction, generationHash);


            final TransactionRepository transactionRepository = repositoryFactory
                    .createTransactionRepository();
            transactionRepository.announce(signedTransaction).toFuture().get();
        }

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

Method #03: Using the CLI

Open a terminal window and run the following command.

bitxor-cli transaction token