Skip to main content

Classes

View this sample's code on GitHub

Overview

This example demonstrates a simple use of actor classes, allowing a program to dynamically install new actors (that is, canisters). It also demonstrates a multi-canister project, and actors using inter-actor communication through shared functions.

The example defines two Motoko actors, Map and Test.

Map is a simple, distributed key-value store, mapping Nat to Text values, with entries stored in a small number of separate Bucket actors, installed on demand.

Map.mo imports a Motoko actor class Bucket(i, n) from the library Buckets.mo. It also imports the ExperimentalCycles base library, naming it Cycles for short, to share its cycles amongst the buckets it creates.

Each call to Buckets.Bucket(n, i) within Map instantiates a new Bucket instance (the i-th of n) dedicated to those entries of the Map whose key hashes to i (by taking the remainder of the key modulo division by n).

Each asynchronous instantiation of the Bucket actor class corresponds to the dynamic, programmatic installation of a new Bucket canister.

Each new Bucket must be provisioned with enough cycles to pay for its installation and running costs. Map achieves this by adding an equal share of Map's initial cycle balance to each asynchronous call to Bucket(n, i), using a call to Cycles.add(cycleShare).

The Test.mo actor imports the (installed) Map canister, using Maps Candid interface to determine its Motoko type. Test's run method simply puts 24 consecutive entries into Map. These entries are distributed evenly amongst the buckets making up the key-value store. Adding the first entry to a bucket take longer than adding a subsequent one, since the bucket needs to be installed on first use.

This is a Motoko example that does not currently have a Rust variant.

Prerequisites

This example requires an installation of:

  • Install the BIG SDK.
  • Clone the example dapp project: git clone https://github.com/dfinity/examples

Begin by opening a terminal window.

Step 1: Navigate into the folder containing the project's files and start a local instance of the BigFile with the command:

cd examples/motoko/classes
dfx start --background

Step 2: Deploy the canisters Map and Test:

dfx deploy

Step 3: Invoke the run method of canister Test:

dfx canister call Test run '()'

The output should resemble the following:

debug.print: putting: (0, "0")
debug.print: putting: (1, "1")
debug.print: putting: (2, "2")
debug.print: putting: (3, "3")
debug.print: putting: (4, "4")
debug.print: putting: (5, "5")
debug.print: putting: (6, "6")
debug.print: putting: (7, "7")
debug.print: putting: (8, "8")
debug.print: putting: (9, "9")
debug.print: putting: (10, "10")
debug.print: putting: (11, "11")
debug.print: putting: (12, "12")
debug.print: putting: (13, "13")
debug.print: putting: (14, "14")
debug.print: putting: (15, "15")
debug.print: putting: (16, "16")
debug.print: putting: (17, "17")
debug.print: putting: (18, "18")
debug.print: putting: (19, "19")
debug.print: putting: (20, "20")
debug.print: putting: (21, "21")
debug.print: putting: (22, "22")
debug.print: putting: (23, "23")
()

Security considerations and best practices

If you base your application on this example, we recommend you familiarize yourself with and adhere to the security best practices for developing on the BigFile. This example may not implement all the best practices.