Persistent storage
Overview
The example dapp shows how to build a simple dapp in Motoko, which will have persistent storage. The dapp is a simple counter, which will increment a counter, retrieve the counter value and reset the counter value by calling backend functions. The functions are exposed through a Candid interface.
The purpose of this example dapp is to build a simple counter dapp, where the counter value will persist even after the dapp has changed and been re-deployed.
This example covers:
- Create new canister smart contract using Motoko.
- Add backend functions for a counter (increment, get count and reset count).
- Deploy the canister smart contract locally.
- Test backend with Candid UI and command line using
dfx
.
Installation
This example project can be cloned, installed and deployed locally, for learning and testing purposes. The instructions are based on running the example on either macOS or Linux, but when using WSL2 on Windows, the instructions will be the same.
Prerequisites
This example requires an installation of:
- Install the IC SDK.
- Download and install git.
- Download the following project files from GitHub: 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 Internet Computer with the command:
cd examples/motoko/persistent-storage
dfx start --background
Step 2: Build and deploy the canister:
dfx deploy
Step 3: Command usage: dfx canister call <project> <function>
dfx canister call persistent_storage increment
Output:
(1 : Nat)
dfx canister call persistent_storage get
Output:
(1 : Nat)
dfx canister call persistent_storage reset
Output:
(0 : Nat)
The persistence of the stored value can be tested by calling the increment
function again and making sure the value is larger than zero. Then make a change in the Motoko code, any minor change like changing the function name get
to getCount
, and then re-deploy the project and call the getCount
function to verify that the counter value did not change back to the initial value (0).
$ dfx canister call persistent_storage increment
(1 : Nat)
// Make code change
$ dfx deploy
$ dfx canister call persistent_storage getCount
(1 : Nat)
Architecture
The two main parts of the example dapp are the backend and the Candid interface. This example project does not have a frontend.
Motoko backend
The backend functions are located in the src/persistent_storage/main.mo
Motoko file. The backend stores the counter value, and has functions to get, increment and reset the counter value. Furthermore the backend insures the counter value persists upgrades of the dapp.
Counter variable
The current counter value is stored as a number in the actor.
actor {
stable var counter : Nat = 0;
}
increment()
The increment()
function increments the counter variable.
public func increment() : async Nat {
counter += 1;
return counter;
};
The function is returning the incremented counter variable.
get()
The get()
function returns the current counter value.
public query func get() : async Nat {
return counter;
};
reset()
The reset()
function resets the counter value to 0 and returns the value.
public func reset() : async Nat {
counter := 0;
return counter;
};
Candid interface
The Candid UI provides an easy, user friendly interface for testing the backend. The UI is automatically generated, and the canister ID can be found by using the dfx canister id <canister_name>
command:
$ dfx canister id __Candid_UI
r7inp-6aaaa-aaaaa-aaabq-cai
$ dfx canister id persistent_storage
rrkah-fqaaa-aaaaa-aaaaq-cai
http://<candid_canister_id>.localhost:4943/?id=<backend_canister_id>