Skip to main content

3.1 Motoko package managers

Intermediate
Tutorial

Overview

Mops and Vessel are package managers for Motoko. In this guide, you'll explore how to download and install Mops and Vessel, then how to import and use different libraries that have been downloaded through a package manager.

What is a package manager?

A package manager is a collection of tools that automates installing, upgrading, configuring, and removing software packages or libraries. They help efficiently manage the dependencies of a project. In relation to Motoko, Mops and Vessel provide workflows for libraries to be downloaded, upgraded, and imported into Motoko code files. Mops supports over 60 libraries for Motoko, spanning several different functionalities such as utility, encoding, cryptography, data structure libraries, and more.

Package managers help simplify things such as update management, since they provide an easy way to update all libraries within your project.

Installing Mops

Mops utilizes a fully on-chain package registry. To install Mops, first be sure to have set up your developer environment and installed the IC SDK and Node.js, as described in the previous module, 0.3: Developer environment setup. Mops is supported in dfx versions 0.10.0 and higher.

Then, to install Mops, run the command:

npm i -g ic-mops

Installing Vessel

To install Vessel, download the Vessel binary from the GitHub release page, with a command such as:

wget https://github.com/dfinity/vessel/releases/download/v0.6.4/vessel-macos

Then, rename vessel-macos to vessel:

mv vessel-macos vessel

Change the file's permissions to include execute permissions:

chmod +x vessel

Finally, to initialize Vessel, run vessel init in your project's root folder.

Using Mops

Creating a new project

To get started, create a new project in your working directory. Open a terminal window, navigate into your working directory (developer_journey), then use the following commands to start dfx and create a new project:

dfx start --clean --background
dfx new mops_example

You will be prompted to select the language that your backend canister will use. Select 'Motoko':

? Select a backend language: ›
❯ Motoko
Rust
TypeScript (Azle)
Python (Kybra)

dfx versions v0.17.0 and newer support this dfx new interactive prompt. Learn more about dfx v0.17.0.

Then, select a frontend framework for your frontend canister. Select 'No frontend canister':

  ? Select a frontend framework: ›
SvelteKit
React
Vue
Vanilla JS
No JS template
❯ No frontend canister

Lastly, you can include extra features to be added to your project:

  ? Add extra features (space to select, enter to confirm) ›
⬚ Internet Identity
⬚ Bitcoin (Regtest)
⬚ Frontend tests

Then, navigate into the new project directory:

cd mops_example

Configuring your project to use Mops

Then, open the dfx.json file within your project. Add Mops as a packtool in the file by adding the following line:

dfx.json
{
"defaults": {
"build": {
"packtool": "mops sources"
}
}
}

Initializing Mops

Then, initialize the Mops configuration with the command:

mops init

You'll be prompted to choose whether you plan to use Mops to pull packages or publish packages:

? Select type: › - Use arrow-keys. Return to submit.
❯ Project (I just want to use mops packages in my project)
Package (I plan to publish this package on mops)

In this case, select 'Project'. For more information about publishing packages, see the publishing a package section.

You will also be prompted to choose if you'd like to use a GitHub workflow. This is optional.

Adding packages to mops.toml.

To install a package with Mops, you need to specify the package in the mops.toml file within your project. To add a package to this file, you can use the command maps add then the package name:

mops add base

Or, you can add packages directly from GitHub by specifying the repository's URL:

mops add https://github.com/dfinity/motoko-base

You can also specify the branch, commit hash, or tag by adding #<branch/tag/hash>:

mops add https://github.com/dfinity/motoko-base#moc-0.9.1

If you have a locally stored package, you can put the source files inside your project's directory, then add them by specifying the path:

mops add ./local-package

Using any of these workflows will add the package to the mops.toml file.

Then, to install all packages specified in this file, use the command:

mops install

Publishing a package

If you develop a package that you'd like to publish so other developers can use it, you can publish it to the Mops registry! For instructions on publishing a package to Mops, check out the Mops documentation.

Using Vessel

To pull a package using Vessel, edit the vessel.dhall file to include what packages your project will import.

Then, edit your dfx.json file to use the packtool of vessel sources:

dfx.json
"defaults": {
"build": {
"packtool": "vessel sources"
}
}

Importing packages into your Motoko code

Once a package has been installed, whether it was installed using Mops or Vessel, you can import them into your Motoko code file using the line import PackageName "mo:<package_name>";.

You've used this command in previous Motoko code examples to import packages such as the Motoko base library. For example, recall the characterCount actor code from the previous module 2.6: Motoko level 2:

src/character_count/main.mo
import Text "mo:base/Text";
import Bool "mo:base/Bool";

actor characterCount {

public func test(text: Text) : async Bool {
let size = Text.size(text);
return size % 2 == 0;
};
};

Need help?

Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The ICP community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out:

Next steps

Next, let's dive into using HTTPS outcalls: