My First Microservice on the Internet Computer

A QR Code Generator in Pure Motoko

Introduction

The Internet Computer is conceived as a secure network protocol that allows untrusted data centers to host trusted microservices on behalf of anyone with internet compute tokens. I set out to build my first microservice on the Internet Computer and thought to share my experiences, which were definitely very positive!

What to build?

I wanted to build something simple, but not trivial. Hence, a microservice to echo hello world or calculate the factorial of a given number would not suffice. It needed to be something I could actually use and integrate into my existing stack. After a quick head scratch, I settled on a QR code generator, which I needed to display cryptocurrency wallet addresses.

How to build it?

Microservices on the Internet Computer run in a WebAssembly virtual machine, so to build a microservice, one simply needs to develop a program that compiles down to WebAssembly. There are several existing libraries to generate QR codes, such those in C and Rust, which compile down to WebAssembly. I easily could have used one of those, but being the adventurous developer that I am, I decided to develop my own in Motoko.

What is Motoko?

Motoko is a high-level language designed by the authors of the WebAssembly specification. It is syntactically similar to Swift and unique in that it provides first class support for microservice composition on the Internet Computer.

To obtain the latest version of the Motoko compiler, one simply needs to download and install the Internet Computer SDK.

$ wget https://sdk.dfinity.org/install.sh

$ yes Y | sh install.sh

Preliminaries

Before defining an interface for my microservice in Motoko, it helps to review the QR code specification to understand the components that make up these ubiquitous matrix barcodes. The symbology breaks down like this:

The relevant parameters needed to produce these components include a version number from 1 to 40, an error correction level of L, M, Q, or H, representing data loss tolerances of 7%, 15%, 25%, and 30%, respectively, and an encoding scheme, which could be numeric, alphanumeric, eight-bit, or Kanji.

Interface Definition

Translating the above into Motoko type definitions gives us the following:

public type Version = { #Version : Nat }; public type ErrorCorrection = { #L; #M; #Q; #H }; public type Mode = { #Alphanumeric; #EightBit; #Kanji; #Numeric }; public type Matrix = { #Matrix : [[Bool]] };

Using these type definitions, we can define a high-level function in Motoko to generate QR codes.

/**

* Encodes the input text according to the QR code specification or

* returns null if the input text is invalid for the given mode.

*/

public func encode(

version : Version, // Version number.

level : ErrorCorrection, // Error correction level.

mode : Mode, // Encoding scheme.

input : Text // Input text.

) : async ?Matrix { .. };

Wrapping the above in a Motoko actor declaration defines the interface.

Implementation

The implementation is available on GitHub. It worked out to just over 2,000 lines of code and required over a dozen supporting modules. The best way to browse the code is by cloning the repository and opening it in Visual Studio, for which there exists a Motoko syntax highlighting extension.

$ git clone https://github.com/enzoh/motoko-qr

$ code qr

The implementation relied heavily on the Motoko standard library, which I found to be relatively mature and featureful. The APIs provided there seem heavily influenced by Rust and Standard ML, and being a user of those languages, I rarely needed to consult any documentation. This was especially fortunate because the documentation website is still under development. Nevertheless, the most up-to-date details could always be found by opening the standard library directly in Visual Studio.

$ code $HOME/.cache/dfinity/versions/$DFX_VERSION/base

Demo

Start a local internet compute replica.

$ dfx start

Execute the following commands in another tab.

$ dfx build

$ dfx canister install --all

$ dfx canister call demo encode \

$ '(variant{Version=2}, variant{M}, variant{Alphanumeric}, "HTTPS://SDK.DFINITY.ORG")' \

$ | sed 's/[(")]//g' \

$ | sed 's/#/█/g'

Observe the following result.