The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.

Managing Assets and Tokens

Introduction

The multichainr package provides a high-level R interface to the MultiChain JSON-RPC API. This vignette demonstrates the lifecycle of managing both fungible assets (like currencies or loyalty points) and non-fungible tokens (NFTs).

To follow this guide, ensure you have the MultiChain binaries (multichaind and multichain-util) installed on your system.

library(multichainr)

# Set the path to your MultiChain binaries
mc_set_path(Sys.getenv("MULTICHAIN_PATH"))

1. Node Initialization

MultiChain operates as a permissioned blockchain. We start by initializing a new chain and launching the daemon.

chain_name <- "asset_demo_chain"

# Create the blockchain configuration
mc_node_init(chain_name)

# Start the node in the background
mc_node_start(chain_name)

# Allow the node a few seconds to initialize the wallet and network
Sys.sleep(3) 

# Connect to the local node
config <- mc_get_config(chain_name)
conn <- mc_connect(config)

2. Permissions and Addresses

By default, MultiChain is secure. Addresses must be granted specific permissions to issue or receive assets.

# Generate new wallet addresses
issuer_addr <- mc_get_new_address(conn)
recipient_addr <- mc_get_new_address(conn)

# Grant 'issue' and 'send' permissions to the issuer
mc_grant(conn, issuer_addr, "issue,send,receive")

# Grant 'receive' permissions to the recipient
mc_grant(conn, recipient_addr, "receive")

3. Fungible Assets

Fungible assets are divisible and interchangeable. We can create an “open” asset to allow the supply to be increased later.

# Define an asset named 'gold' with 2 decimal places (units = 0.01)
gold_params <- list(name = "gold", open = TRUE)

# Initial issuance of 1,000 units
mc_issue(conn, issuer_addr, gold_params, quantity = 1000, units = 0.01)

# Increase the total supply by an additional 500 units
mc_issue_more(conn, issuer_addr, "gold", 500)

# Verify the balance of the issuer
issuer_balances <- mc_get_address_balances(conn, issuer_addr)
print(issuer_balances)

4. Non-Fungible Tokens (NFTs)

In MultiChain 2.x, NFTs are managed as unique tokens within a non-fungible “Parent Asset.”

Creating the NFT Parent

To support individual tokens, the parent asset must be created with fungible = FALSE and an initial quantity of 0.

art_params <- list(
  name = "art", 
  fungible = FALSE, 
  open = TRUE
)

# Issue the parent container
mc_issue(conn, address = issuer_addr, name = art_params, quantity = 0, units = 1)

Issuing Unique Tokens

Once the parent exists, we can issue individual tokens (NFTs). Each token can include custom JSON metadata.

# Issue a unique token "painting_001" with specific metadata
mc_issue_token(conn,
               address = issuer_addr, 
               asset = "art", 
               token = "painting_001", 
               quantity = 1, 
               token_details = list(artist = "Leonardo da Vinci", year = 1503))

# Retrieve specific token metadata
token_info <- mc_get_token_info(conn, "art", "painting_001")
print(token_info)

5. Transfers and Multibalances

We can transfer assets using specific convenience functions or the general-purpose mc_send function for complex transactions (like NFTs).

# 1. Send 100 units of fungible 'gold'
mc_send_asset(conn, recipient_addr, "gold", 100)

# 2. Send the NFT 'painting_001'
# NFTs require a nested list structure specifying the parent and the token name
nft_transfer <- list(
  art = list(
    token = "painting_001",
    qty = 1
  )
)
mc_send(conn, recipient_addr, nft_transfer)

# 3. Inspect the recipient's token balances
# The output is a clean data frame with an 'address' column
recipient_tokens <- mc_get_token_balances(conn, recipient_addr)
print(recipient_tokens)

6. Node Shutdown and Cleanup

When the work is complete, it is important to stop the node and, if necessary, remove the data directory.

mc_node_stop(conn)
Sys.sleep(2)

# Determine data directory for cleanup
if (.Platform$OS.type == "windows") {
  base_dir <- file.path(Sys.getenv("APPDATA"), "MultiChain")
} else if (Sys.info()["sysname"] == "Darwin") {
  base_dir <- file.path(Sys.getenv("HOME"), "Library/Application Support/MultiChain")
} else {
  base_dir <- file.path(Sys.getenv("HOME"), ".multichain")
}

chain_dir <- file.path(base_dir, chain_name)
if (dir.exists(chain_dir)) unlink(chain_dir, recursive = TRUE)

Summary

In this vignette, we demonstrated how to:

  1. Configure permissions using mc_grant.
  2. Issue open fungible assets using mc_issue and mc_issue_more.
  3. Set up a non-fungible environment by setting fungible = FALSE.
  4. Issue and query unique tokens (NFTs) via mc_issue_token and mc_get_token_info.
  5. Perform multi-asset transfers and monitor balances.

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.