moxzi
Docs / Getting started / Your first actor

Your first actoralpha

Build a counter actor, run it with moxzid, call it over HTTP, upgrade it without losing state, and restart the server.

In this tutorial you'll write a small Motoko actor, host it with moxzid, call its methods with curl, and then change its code while it's running. The counter's value survives both the upgrade and a server restart.

You need moxzi installed and curl. Run each command from the same empty directory.

1. Write the actor#

Save this as counter.mo:

counter.mo
actor {
  var count : Nat = 0;

  public func inc() : async Nat {
    count += 1;
    count
  };

  public query func get() : async Nat {
    count
  };
};

A Motoko actor is an object that receives messages one at a time. inc is an update: it can change state, and the change is kept. get is a query: it reads state and can't change it. Every var in an actor keeps its value across upgrades without any extra code.

2. Build it#

moxzi build counter.mo
counter.mo -> counter.wasm + counter.did (245600 bytes, 1 file(s), 50 steps, 0.67s)
compiled by ~/.local/lib/moxzi/compiler.wasm (sha256 9294817c6e9069cbd0e712d0e9dde0ec1b6893d0e7b42d798fa3dd4c8cd772cb), moxzi 0.1.0-alpha.10

This writes counter.wasm, which you'll run, and counter.did, the actor's Candid interface.

3. Start the server#

moxzid reads a manifest listing the actors to host. Save this as actors.json:

actors.json
{
  "actors": [
    { "name": "counter", "wasm": "counter.wasm" }
  ]
}

Start the server in a second terminal, in the same directory:

moxzid -m actors.json -s ./state

-s ./state tells moxzid to save each actor's state under ./state. Without it, everything is held in memory and lost when the server stops.

The server listens on 127.0.0.1:7000. Use 127.0.0.1 rather than localhost in the commands below: on macOS, localhost:7000 can reach the AirPlay Receiver instead.

4. Call it#

Each method is available at /call-json/<actor>/<method> for updates and /query-json/<actor>/<method> for queries. The request body is a JSON array of the method's arguments; these methods take none, so it's []. The reply is a JSON array of the results. (-w '\n' makes curl print a newline after the reply.)

curl -s -w '\n' -d '[]' http://127.0.0.1:7000/call-json/counter/inc
curl -s -w '\n' -d '[]' http://127.0.0.1:7000/call-json/counter/inc
curl -s -w '\n' -d '[]' http://127.0.0.1:7000/query-json/counter/get
[1]
[2]
[2]

5. Upgrade it#

Add a reset method. Replace counter.mo with:

counter.mo
actor {
  var count : Nat = 0;

  public func inc() : async Nat {
    count += 1;
    count
  };

  public query func get() : async Nat {
    count
  };

  public func reset() : async () {
    count := 0;
  };
};

Rebuild, then send the new module to the running server:

moxzi build counter.mo
curl -s --data-binary @counter.wasm http://127.0.0.1:7000/upgrade/counter
counter.mo -> counter.wasm + counter.did (246247 bytes, 1 file(s), 51 steps, 0.78s)
compiled by ~/.local/lib/moxzi/compiler.wasm (sha256 9294817c6e9069cbd0e712d0e9dde0ec1b6893d0e7b42d798fa3dd4c8cd772cb), moxzi 0.1.0-alpha.10
upgraded

The count is still 2:

curl -s -w '\n' -d '[]' http://127.0.0.1:7000/query-json/counter/get
[2]

An upgrade replaces the actor's code and keeps its state. If the new code can't read the old state (for example, you changed count from Nat to Text), moxzid refuses the upgrade, says why, and keeps running the old code. Migrations covers how to change the type of stored data.

6. Restart the server#

Stop moxzid with Ctrl-C and start it again with the same command. It saves every actor on the way out and restores them on the way in:

moxzid -m actors.json -s ./state

Back in the first terminal:

curl -s -w '\n' -d '[]' http://127.0.0.1:7000/query-json/counter/get
curl -s -w '\n' -d '[]' http://127.0.0.1:7000/call-json/counter/reset
curl -s -w '\n' -d '[]' http://127.0.0.1:7000/query-json/counter/get
[2]
[]
[0]

The count came back as 2, and the new reset method works. State also survives a crash: moxzid writes each update to a log before running it, so after kill -9 it replays the log on startup. See Persistence.

What you built#

The same counter.wasm can be installed on the Internet Computer with dfx or icp, loaded in a browser with moxzi-web, or run inside an actor platform.

Next steps#

On this page1. Write the actor2. Build it3. Start the server4. Call it5. Upgrade it6. Restart the serverWhat you builtNext steps