当前位置:网站首页>Dfinity (ICP) basic development tutorial-5
Dfinity (ICP) basic development tutorial-5
2022-06-13 08:01:00 【Boiled soybeans in brine】
Dfinity Basic development course
Tutorial overview
Quick start provides a simple default application quick path to deploy without stopping to enjoy the scenery along the way .
This article introduces specific scenarios , It also points out the actions and details to be performed in each step .
If quickstarts and tutorials don't exactly fit your style , This overview memo summarizes the steps to follow for quick reference .
install DFINITY Canister SDK after , You need to know all of the following :
Create a new project and switch to the project directory .
dfx new <project_name> && cd <project_name>>Edit the backend that defines your service or application .
Edit the... That provides the front end for your service or application HTML、JavaScript and CSS.
start-up Internet Computers are developed locally or checked with Internet Computer connection for network deployment .
Register locally or on the network 、 Build and deploy .
dfx deploy --network <network>View your service or application in the browser .
Explore default projects
If you start using DFINITY SDK And fast start , You've seen , Used to create Internet The basic workflow of an application running on a computer . Now? , Let's take a closer look at this workflow by exploring the default files and folders that are added to the workspace when a new project is created .
As Preview , The following figure illustrates running locally on your computer Internet The development workflow of computer time .

Before we start
Before you start this tutorial , Please verify the following :
- You have an Internet connection and can access local macOS or Linux On the computer shell terminal .
node.jsIf you want to include the default template file for front-end development in your project , You have installed .- You have downloaded and installed DFINITY Canister SDK package
- If you use Visual Studio Code As IDE, You have made a reservation for Motoko Installed Visual Studio Code plug-in unit .
- You have stopped any... Running on the local computer Internet Computer network processes .
Completing this tutorial takes approximately 20 minute .
Create a new project
Internet The computer's application is created as project start-up . You can use dfx Executable command line interface (CLI) Create project .
Take a closer look at the files and folders that are included in the project by default , Let's create a new project to use .
To create a new project :
If you haven't opened , Please open a terminal shell on the local computer .
If you use a separate working folder , Please navigate to the page you used to Internet Folder for computer projects .
Create a new project by running the following command :
dfx new explore_helloThe
dfx new explore_helloThe command will create a newexplore_helloproject , Include the default project directory structure under the new project name and the new project Git The repository . If alreadynode.jsInstalled locally , The new project will also add some template front-end code and dependencies .To ensure that the project name is in JavaScript、Motoko And other contexts , You should only use alphanumeric characters and underscores . Cannot contain dashes or any special characters .
View the default directory structure by running the following command :
ls -l explore_helloBy default , The project directory structure includes at least one source subdirectory 、 A template
README.mdFile and a defaultdfx.jsonThe configuration file .Depending on whether you have
node.jsinstall , Your project directory may contain some or all of the following files :explore_hello/ ├── README.md # default project documentation ├── dfx.json # project configuration file ├── node_modules # libraries for front-end development ├── package-lock.json ├── package.json ├── src # source files directory │ ├── explore_hello │ │ └── main.mo │ └── explore_hello_assets │ ├── assets │ │ ├── logo.png │ │ ├── main.css │ │ └── sample-asset.txt │ └── src │ ├── index.html │ └── index.js └── webpack.config.jsThe default project directory includes at least the following folders and files :
READMEThe default file used to record items in the repository .dfx.jsonThe default configuration file used to set configurable options for the project .srcThe default directory for all source files required by the application .
Default
srcThe directory contains a templatemain.mofile , You can modify or replace this file to include your core programming logic .Because this tutorial focuses on the basics of getting started , So you will only use this
main.mofile . If you havenode.jsinstall , Your project directory will contain other files and directories , You can use them to define the front-end interface of your application . Front end development and documentationassetsThe template file in the folder will be discussed later .
View default configuration
By default , Creating a new project will add some template files to your project directory . You can edit these template files to customize the configuration settings of the project and include your own code to speed up the development cycle .
To view the project's default configuration file :
If you haven't opened , Please open a terminal shell on the local computer .
Switch to your project directory by running the following command :
cd explore_hellodfx.jsonOpen the configuration file in a text editor to view the default settings .for example :
{ "canisters": { "explore_hello": { "main": "src/explore_hello/main.mo", "type": "motoko" }, "explore_hello_assets": { "dependencies": [ "explore_hello" ], "frontend": { "entrypoint": "src/explore_hello_assets/src/index.js" }, "source": [ "src/explore_hello_assets/assets", "dist/explore_hello_assets/" ], "type": "assets" } }, "defaults": { "build": { "packtool": "" } }, "dfx": "0.7.2", "networks": { "local": { "bind": "127.0.0.1:8000", "type": "ephemeral" } }, "version": 1 }Let's look at some default settings .
The
canistersPartial designationexplore_helloProject WebAssembly The name of the module isexplore_hello.Described
canisters.explore_hellokey Specifies that the main program to be compiled is located in the path specified by themainSet up , under these circumstances ,src/explore_hello/main.moAndtypeSetting indicates that this is amotokoProgram .stay
canisters.explore_hello_assetsThe front-end asset key of this project specifies the configuration details . Let's skip these .The
dfxSettings are used to identify the software version used to create the project .The
networksSection specifies information about the network you are connected to . The default setting will be local Internet The computer network is bound to the local host address127.0.0.1And port8000.If you can access other Internet Computer network providers , Then
networksThe section can contain network aliases and for connecting to these providers URL.
You can keep the default settings .
close
dfx.jsonFile to continue .
View the default program code
New projects always contain a template main.mo Source code file . You can edit this file to include your own code to speed up the development cycle .
Let's look at the default main.mo Sample program in template file , As a use Motoko Programming languages are the starting point for creating simple programs .
To view the default sample program for the project :
Check that you are still in the project directory by running the following command :
pwdsrc/explore_hello/main.moOpen the file in a text editor and view the code in the template :actor { public func greet(name : Text) : async Text { return "Hello, " # name # "!"; }; };Let's look at some of the key elements of this program :
- You might notice , This sample code defines a
actorinstead ofmainSome programming languages require functions . about Motoko, ThemainFunctions are implicit in the file itself . - Although traditional “Hello, World!” The program explains how to use
printorprintlnFunction to print a string , This traditional procedure does not represent the Internet Running on a computer Motoko A typical use case for a program . - This sample program defines a
actorwith publicgreetfunction , Instead of a print function , It acceptsnameA parameter of typeText. - Then the program uses
asyncKeyword to indicate that the program returns an asynchronous message , This message is used by"Hello, "、#Operator 、nameParameter and constructed concatenated text string"!".
We'll explore using more later
actorObject and asynchronous message processing code . Now? , You can go on to the next part .- You might notice , This sample code defines a
close
main.moFile to continue .
Start the local network
Before building the default project , You need to connect to Internet computer network , Or in your development environment Local function , Or on a subnet that you can access long-range function .
Starting the network locally requires a dfx.json file , So you should make sure that you are in the root directory of the project . For this tutorial , You should have two separate terminal housings , So that you can start and view network operations in a terminal , And manage your project in another terminal .
Start the network locally :
Open a new terminal window or a new terminal tab on the local computer .
If necessary, , Navigate to the root directory of the project .
- You should now open Two terminals .
- You should Project directory As you Current working directory .
Start on the local computer by running the following command Internet computer network :
dfx startDepending on your platform and local security settings , You may see a warning displayed . If you are prompted to allow or deny incoming network connections , Please click on the allow .
After starting the local network , You have a terminal that displays messages about network operations , The other terminal is used to perform project related tasks .
Keep the terminal displaying network operation open , And switch the focus to the terminal where you create a new project .
Register container identifier
Before you connect to a that runs locally in your development environment Internet After the computer network , You can register with the network , To generate unique for your project 、 Network specific Container Identifier .
In the quick start tutorial , This step is done as dfx deploy Part of the command workflow . This tutorial demonstrates how to perform each operation independently .
To register the container identifier for the local network :
if necessary , Please check if you are still in the project directory .
Register a unique container identifier for the containers in the project by running the following command :
dfx canister create --allThe command shows
dfx.jsonNetwork specific container identifier of the container defined in the configuration file .Creating a wallet canister on the local network. The wallet canister on the "local" network for user "pubs-id" is "rwlgt-iiaaa-aaaaa-aaaaa-cai" Creating canister "explore_hello"... "explore_hello" canister created with canister id: "rrkah-fqaaa-aaaaa-aaaaq-cai" Creating canister "explore_hello_assets"... "explore_hello_assets" canister created with canister id: "ryjl3-tyaaa-aaaaa-aaaba-cai"Because you are connected to a locally running Internet computer network , Therefore, these container identifiers are only valid locally , And stored in... For the project
.dfx/local/canister_ids.jsonIn file .for example :
{ "explore_hello": { "local": "rrkah-fqaaa-aaaaa-aaaaq-cai" }, "explore_hello_assets": { "local": "ryjl3-tyaaa-aaaaa-aaaba-cai" } }
compiler
Now you have explored the default configuration settings and program code and started Internet Computer The Internet , Let's compile the default program into an executable WebAssembly modular .
To build a program executable :
A terminal on the local computer shell in , Navigate to your
explore_helloProject directory .You must
dfx buildRun this command from the project directory structure .Build an executable container by running the following command :
dfx buildYou should see output similar to the following :
Building canisters... Building frontend...Because you are connected to a locally running Internet computer network , So it's time to
dfx buildThe command will appear in the projectcanistersAdd directory under directory.dfx/local/.Verify by running the following command
.dfx/local/canisters/explore_helloThedfx buildWhether the directory created by the command contains WebAssembly And related application files .ls -l .dfx/local/canisters/explore_hello/for example , This command returns output similar to the following :
-rw-r--r-- 1 pubs staff 178 Apr 6 14:25 explore_hello.d.ts -rw-r--r-- 1 pubs staff 41 Apr 6 14:25 explore_hello.did -rw-r--r-- 1 pubs staff 155 Apr 6 14:25 explore_hello.did.js -rw-r--r-- 1 pubs staff 142 Apr 6 14:25 explore_hello.js -rw-r--r-- 1 pubs staff 157613 Apr 6 14:25 explore_hello.wasmThe
canisters/explore_helloThe directory contains the following key files :- The
explore_hello.didThe file contains the interface description of the main program . - The
explore_hello.did.jsThe file contains the container interface of the function in the program JavaScript Express . - The
explore_hello.jsThe file contains the container interface of the program JavaScript Express . - The
explore_hello.wasmThe file contains compiled for the assets used in the project WebAssembly.
The
canisters/explore_hello_assetsThe directory contains similar files that describe the front-end assets associated with your project .except
canisters/explore_helloandcanisters/explore_hello_assetsOutside the files in the directory , Thedfx buildThe command also creates aidlCatalog .- The
Deploy the project locally
You have seen this dfx build Command in canisters Multiple artifacts are created in the directory of your project .canister_manifest.json To be in Internet Deploy your programs on the computer network , need WebAssembly Modules and files .
Local deployment :
A terminal on the local computer shell in , Navigate to your
explore_helloProject directory .explore_helloDeploy your project on the local network by running the following command :dfx canister install --allThis command displays output similar to the following :
Installing code for canister explore_hello, with canister_id rrkah-fqaaa-aaaaa-aaaaq-cai Installing code for canister explore_hello_assets, with canister_id ryjl3-tyaaa-aaaaa-aaaba-cai Authorizing our identity (pubs-id) to the asset canister... Uploading assets to asset canister... /index.html 1/1 (480 bytes) /index.js 1/1 (296836 bytes) /main.css 1/1 (484 bytes) /sample-asset.txt 1/1 (24 bytes) /logo.png 1/1 (25397 bytes) /index.js.map 1/1 (964679 bytes) /index.js.LICENSE.txt 1/1 (499 bytes)function
dfx canister callCommand and specify the program and function to call by running the following command :dfx canister call explore_hello greet everyoneThis command specifies :
explore_helloAs you want to call Containers Or the name of the application service .greetAs the specific... You want to call Method Or functions .everyoneAs passed togreetThe parameters of the function .
Verify command display
greetThe return value of the function .for example :
("Hello, everyone!")
View the default front end
If you have node.js Installed in your development environment , Your project will include a simple front-end example , This example uses a template index.jsJavaScript file explore_hello Access the program in the browser .
To explore the default front-end templates :
Open a terminal on the local computer shell( If you haven't opened ), Then navigate to your
explore_helloProject directory .src/explore_hello_assets/src/index.jsOpen the file in a text editor and view the code in the template script :import { Actor, HttpAgent } from '@dfinity/agent'; import { idlFactory as explore_hello_idl, canisterId as explore_hello_id } from 'dfx-generated/explore_hello'; const agent = new HttpAgent(); const explore_hello = Actor.createActor(explore_hello_idl, { agent, canisterId: explore_hello_id }); document.getElementById("clickMeBtn").addEventListener("click", async () => { const name = document.getElementById("name").value.toString(); const greeting = await explore_hello.greet(name); document.getElementById("greeting").innerText = greeting; });Templates
index.jsThe file uses twoimportStatement to explicitly create proxy instances andexplore_hellofromdfx.This file and template
index.htmlFiles are used in conjunction to display assets with images 、 Input fields andgreetFunction button HTML page .close
index.jsFile to continue .View the front-end assets created for the project by running the following command :
ls -l .dfx/local/canisters/explore_hello_assets/This command displays output similar to the following :
drwxr-xr-x 9 pubs staff 288 Apr 6 14:25 assets -r--r--r-- 1 pubs staff 2931 Dec 31 1969 assetstorage.did -r--r--r-- 1 pubs staff 265823 Dec 31 1969 assetstorage.wasm -rw-r--r-- 1 pubs staff 3651 Apr 6 14:25 explore_hello_assets.d.ts -rw-rw-rw- 1 pubs staff 2931 Dec 31 1969 explore_hello_assets.did -rw-r--r-- 1 pubs staff 4236 Apr 6 14:25 explore_hello_assets.did.js -rw-r--r-- 1 pubs staff 149 Apr 6 14:25 explore_hello_assets.js -rw-rw-rw- 1 pubs staff 265823 Dec 31 1969 explore_hello_assets.wasmThese documents are made by
dfx buildThe command uses node modules and templatesindex.jsThe files are generated automatically .Open the browser , Then navigate to
localPort number and network address -127.0.0.1:8000/in -specifieddfx.jsonThe configuration file .To specify what you want Web The server shows
canisterIdOfexplore_hello_assetsContainers , Use the following syntax to combine parameters with The container identifier is added to URL:?canisterId=<YOUR-CANISTER-IDENTIFIER>for example , complete URL Should be similar to the following :
http://127.0.0.1:8000/?canisterId=rrkah-fqaaa-aaaaa-aaaaq-caiVerify that you see the... Of the sample application HTML page .
for example :

- Type a greeting , And then click “** Click me ”** To return a greeting .

Stop the local network
After you have finished testing the program , You can stop local Internet computer network , So that it will not continue to run in the background .
To stop the local network :
In the terminal that displays the network operation , Press Control-C Interruptible local network processes .
Stop... By running the following command Internet computer network :
dfx stop
Use actor Inquire about
In the QuickStart , For the first time, you see a simple Internet A computer program , It contains a participant object and asynchronous messaging . As the next step in learning to write programs that leverage participant based messaging , This tutorial explains how to modify the legacy Hello, World! Procedures to define participants , Then deploy and test your program on your local network .
Before you start
Before you start this tutorial , Please verify the following :
- You have downloaded and installed DFINITY Canister SDK package ,
- You have stopped any... Running on the local computer Internet Computer network processes .
Completing this tutorial takes approximately 20 minute .
Create a new project
To create a new project for this tutorial :
If you haven't opened , Please open a terminal shell on the local computer .
If you are using Internet Computer project , Please switch to the one you use for Internet Folder for computer projects .
Create a new project by running the following command :
dfx new actor_helloSwitch to your project directory by running the following command :
cd actor_hello
Modify default configuration
You see that creating a new project will default to dfx.json Add the configuration file to your project directory . In this tutorial , You need to change some default settings to reflect your project .
modify dfx.json The configuration file :
dfx.jsonOpen the configuration file in a text editor .Check
actor_helloDefault settings for the project .Please note that , The names and paths of both source and output files use
actor_helloProject name .for example , The default container name is
actor_hello, The default path of the main program file issrc/actor_hello/main.mo.You can rename any of these files or directories . however , If you make any changes , Make sure that the names of the files and directories you use on the file system are the same as those you use in
dfx.jsonThe name specified in the configuration file matches . If you plan to use the default directory and file name , There is no need to change .actor_hello_assetsRemove all configuration settings from the file .The sample program for this tutorial does not use any front-end assets , So you can remove these settings from the configuration file .
for example , Delete the
actor_hello_assetsThe configuration file after the section is as follows :{ "canisters": { "actor_hello": { "main": "src/actor_hello/main.mo", "type": "motoko" } }, "defaults": { "build": { "packtool": "" } }, "dfx": "0.7.2", "networks": { "local": { "bind": "127.0.0.1:8000", "type": "ephemeral" } }, "version": 1 }Save your changes and close the file to continue .
Modify the default program
You see that creating a new project will create a src With template main.mo Default directory for files . In this tutorial , You will modify the template code to create a simple “Hello, World!” Use the actor's program .
Modify the default template source code :
Switch to the source directory of the project by running the following command :
cd src/actor_hellomain.moOpen the template file in a text editor and delete the existing content .The next step is to write a program , Print a similar to the traditional “Hello, World!” Statement program . The sample program . however , for Internet Computer compiler , Your program must contain a
actorhavepublicObject of function .Copy and paste the following sample code into
main.moIn file :import Debug "mo:base/Debug"; actor HelloActor { public query func hello() : async () { Debug.print ("Hello, World from DFINITY \n"); } };Let's take a closer look at this simple program :
- The program imports a
DebugModule to provideprintfunction . - The program uses
public query funcTo define the query method , Because in this case ,actor_helloThe program does not make any changes to the state of the container , Nor will you perform any operation that will update the data you are accessing .
- The program imports a
Save your changes and close
main.mofile .
Use local identifiers to build programs
You may only use this simple program for some local tests . therefore , No need to Internet A unique container identifier is reserved on the computer network to store the compiled output of the program .
under these circumstances , You can connect at all Internet In case of computer network, compile the program . contrary , The dfx build The command creates a local 、 Hard coded container identifiers for you to use .
You can use this local identifier when testing your program or whenever you want to compile your program , Without having to start locally Internet A computer copy process or a copy connected to a remote subnet .
To build a program executable :
Navigate back to the root of the project directory .
By running the following command , Use locally defined identifiers to build programs :
dfx build --checkThe
--checkOption enables you to build the project locally to verify that it compiles and checks the generated files . Because of thedfx build --checkCommand generates only a temporary identifier , You should see output similar to the following :Building canisters to check they build ok. Canister IDs might be hard coded. Building canisters...xxxxxxxxxx Building canisters to check they build ok. Canister IDs might be hard coded.Building canisters...If the program compiles successfully , You can check the default
.dfx/local/canistersContents and.dfx/local/canisters/actor_hello/Output in subdirectories .for example , You can use the following
treeCommand to view the created file :tree .dfx/local/canistersThis command displays output similar to the following
.dfx/local/canisters
├── actor_hello
│ ├── actor_hello.d.ts
│ ├── actor_hello.did
│ ├── actor_hello.did.js
│ ├── actor_hello.js
│ └── actor_hello.wasm
└── idl
2 directories, 5 files
Deployment project
You can't put dfx build --check The output of the command is deployed to any Internet computer network . If you want to deploy this project , You need to do the following :
- Connect to Internet computer network .
- Register network specific container identifiers .
- Deploy container .
Let's consider these steps in more detail . Before deploying this project , You must connect to Internet computer network , Or in your development environment Local function , Or on a subnet that you can access long-range function . After connecting to a local or remote network , You must also generate a unique 、 given On Online Container identifier to replace the locally defined identifier . See for yourself the steps involved , Let's deploy the project locally .
To deploy this project locally :
if necessary , Open the terminal and navigate to your project directory .
Start on the local computer by running the following command Internet computer network :
dfx start --backgroundFor this tutorial , You can use the
--backgroundOption will Internet The computer network starts as a background process . Use this option , You can go on to the next step , There is no need to open another terminal shell on the local computer .By running the following command , In the local Internet Generate a new container identifier for your project on the computer network :
dfx canister create actor_helloYou should see output similar to the following :
Creating a wallet canister on the local network. The wallet canister on the "local" network for user "pubs-id" is "rwlgt-iiaaa-aaaaa-aaaaa-cai" Creating canister "actor_hello"... "actor_hello" canister created with canister id: "rrkah-fqaaa-aaaaa-aaaaq-cai"The
dfx canister createThe command will also specify the network specific container identifiercanister_ids.jsonStored in.dfx/localFiles in the directory .for example :
{ "actor_hello": { "local": "rrkah-fqaaa-aaaaa-aaaaq-cai" } }actor_helloDeploy your project on the local network by running the following command :dfx canister install actor_helloThis command displays output similar to the following :
Installing code for canister actor_hello, with canister_id rrkah-fqaaa-aaaaa-aaaaq-cai
Query container
You have now deployed the program locally Internet On the computer network Containers , And you can use the dfx canister call Command to test your program .
To test your application deployed on your local network :
Used by running the following command
dfx canister callTo call thishellofunction :dfx canister call actor_hello helloThe validation command returns
helloFunction and the checkpoint message in the terminal running the local network process .for example , The program displays in output similar to “Hello, World from DFINITY”:
[Canister rrkah-fqaaa-aaaaa-aaaaq-cai] Hello, World from DFINITYPlease note that , If you are running on a separate terminal rather than in the background Internet computer network , Will be displayed in the terminal displaying network activity “Hello, World from DFINITY” news .
Stop the local network
After you have finished testing the program , You can stop local Internet computer network , So that it will not continue to run in the background .
To stop the local network :
In the terminal that displays the network operation , Press Control-C Interruptible local network processes .
Stop... By running the following command Internet computer network :
dfx stop
Passing text parameters
This tutorial provides a simple variation of the default program , It allows you to pass a single text parameter to a single actor, Compile the code to create a container , Then retrieve the parameter .
This tutorial explains how to use Candid Interface description language (IDL) Pass parameters on the command line of the terminal , And how to modify the program to allow it to accept multiple text parameter values .
Before you start
Before you start this tutorial , Please verify the following :
- You have downloaded and installed DFINITY Canister SDK package
- You have stopped any... Running on the local computer Internet Computer network processes .
Completing this tutorial takes approximately 20 minute .
Create a new project
To create a new project for this tutorial :
If you haven't opened , Please open a terminal shell on the local computer .
If you are using Internet Computer project , Please switch to the one you use for Internet Folder for computer projects .
Create a new project by running the following command :
dfx new location_helloSwitch to your project directory by running the following command :
cd location_hello
Modify default configuration
Creating a new project will default to dfx.json Add the configuration file to your project directory . You should always review the default settings in the file , To verify that the information accurately reflects the project settings you want to use . For this tutorial , You will modify the default configuration to remove unused settings .
To be modified dfx.json Settings in the configuration file :
dfx.jsonOpen the configuration file in a text editor .Check
location_helloDefault settings for the project .Remove all unnecessary configuration settings .
Since this tutorial does not cover creating any front-end assets , So you can
location_hello_assetsRemove all configuration settings from the file .Save your changes and close the file to continue .
Modify the default program
You see that creating a new project will create a src With template main.mo Default directory for files .
Modify the default template source code :
src/location_hello/main.moOpen the source code file in a text editor .Modify the default source code , use
greetFunction substitutionlocationfunction , usenameParameter substitutioncityParameters .for example :
actor { public func location(city : Text) : async Text { return "Hello, " # city # "!"; }; };Save your changes and close the file to continue .
Start the local network
Before building the project , You need to connect to Internet computer network , Or run it locally in your development environment , Or run remotely on a subnet that you can access .
Starting the network locally requires a dfx.json file , So you should make sure that you are in the root directory of the project . For this tutorial , You should have two separate terminal housings , So that you can start and view network operations in a terminal , And manage your project in another terminal .
To start the local network :
Open a new terminal window or tab on the local computer .
If necessary, , Navigate to the root directory of the project .
- You should now open Two terminals .
- You should Project directory As you Current working directory .
Start on the local computer by running the following command Internet computer network :
dfx startIf you are prompted to allow or deny incoming network connections , Please click on the allow .
Keep the terminal displaying network operation open , And switch the focus to the original terminal where you created the project .
register 、 Build and deploy applications
Before you connect to a that runs locally in your development environment Internet After the computer network , You can register locally 、 Build and deploy your application .
Deploy the application locally :
if necessary , Please check that you are still in the root directory of the project .
Register by running the following command 、 Build and deploy your application :
dfx deployOf
dfx deployOutput display information about the operation it performs .
Passing text parameters
You have now deployed the program locally Internet On the computer network Containers , And you can use dfx canister call Command to test your program .
To test your locally deployed programs :
call
locationMethod in the program and pass by running the following commandcityType parametertext:dfx canister call location_hello location "San Francisco"Because the parameters in this example are in
SanAnd contain a space betweenFrancisco, So you need to enclose the parameters in quotation marks . This command displays output similar to the following :("Hello, San Francisco!")If the parameter does not contain spaces that require the text to be enclosed in quotation marks , You may allow Candid Interface description language infers data types , As shown below :
dfx canister call location_hello location ParisCandid The inferred data type is
Text, And return the output of the program as text , As shown below :("Hello, Paris!")call
locationThe methods in the program are notcityUsing text parameters Candid Interface description language syntax explicitly passes parameters :dfx canister call location_hello location '("San Francisco and Paris")'This command displays output similar to the following :
("Hello, San Francisco and Paris!")Because your program accepts only one text parameter , So specifying multiple strings will only return the first parameter .
for example , If you try this command :
dfx canister call location_hello location '("San Francisco","Paris","Rome")'only
("Hello, San Francisco!")Return the first parameter — — .
Modify the source code in the program
To extend what you have learned in this tutorial , You may want to try to modify the source code to return different results . for example , You may want to modify location Function to return multiple city names .
Try to modify the source code of this tutorial :
dfx.jsonOpen the configuration file in a text editor and the defaultlocation_helloThe setting is changed tofavorite_cities.For this step , You should change the container name and the path of the main program , For container use
favorite_cities.Save your changes and close
dfx.jsonFile to continue .Copy... By running the following command
location_helloSource file directory to matchdfx.jsonThe name specified in the configuration file :cp -r src/location_hello src/favorite_citiessrc/favorite_cities/main.moOpen the file in a text editor .Copy and paste the following code example to
locationReplace this function with two new functions .for example :
actor { public func location(cities : [Text]) : async Text { return "Hello, from " # (debug_show cities) # "!"; }; public func location_pretty(cities : [Text]) : async Text { var str = "Hello from "; for (city in cities.vals()) { str := str # city #", "; }; return str # "bon voyage!"; } };You may notice
TextIn this code example, we use ([ ]) Enclosed in brackets . In terms of itself ,TextRepresenting a group UTF-8 character . Square brackets around a type indicate that it is of that type Array . therefore , In this context ,[Text]Means a group UTF-8 Character set , Enables programs to accept and return multiple text strings .The code example also uses
applyBasic format of array operation , Can be abstracted as :public func apply<A, B>(fs : [A -> B], xs : [A]) : [B] { var ys : [B] = []; for (f in fs.vals()) { ys := append<B>(ys, map<A, B>(f, xs)); }; ys; };Information about functions that perform operations on arrays , see also Motoko Base library or Motoko Programming language reference Chinese vs Array Module description
Register by running the following command 、 Build and deploy applications :
dfx deployBy running the following command , call
locationThe methods in the program are notcityUse Candid Interface description syntax passes parameters :dfx canister call favorite_cities location '(vec {"San Francisco";"Paris";"Rome"})'The command uses Candid Interface description syntax
(vec { val1; val2; val3; })Return value vector . of Candid More information about the interface description language , see also Candid Language Guide .This command displays output similar to :
dfx canister call favorite_cities location '(vec {"San Francisco";"Paris";"Rome"})'Call... By running the following command
location_prettyThe methods in the program are notcityUse interface description syntax to pass parameters :dfx canister call favorite_cities location_pretty '(vec {"San Francisco";"Paris";"Rome"})'This command displays output similar to the following :
("Hello from San Francisco, Paris, Rome, bon voyage!")
Test functions in the browser
Container interface description language ( Often referred to as Candid Or more generally called IDL) Provides a common language for specifying container service signatures .Candid It provides you with a unified way to interact with containers written in different languages or accessed with different tools . for example , Whether the underlying program is native Rust、JavaScript still Motoko,Candid All provide a consistent view of services .Candid Different tools are also supported ( for example dfx Command line interface and network neural system application ) To share a common description of the service .
be based on actor Type signature of ,Candid One is also provided Web Interface , Allows you to call container functions for testing and debugging .
Use dfx deployordfx canister install Command after the project is deployed locally , You can access... In your browser Candid Web Interface endpoint . this Web Interface (Candid UI) Expose the service description as a form , Enables you to quickly view and test functions and try to enter different data types , Without writing any front-end code .
To use Candid Web Interface to test container functions :
Use
dfx canister id __Candid_UICommand to find the Candid UI Container Identifier .dfx canister id __Candid_UIThe command shows Candid UI Container identifier for , The output is similar to the following :
r7inp-6aaaa-aaaaa-aaabq-caiCopy Candid UI Container Identifier , So that it is available on the clipboard .
If you have stopped Internet Computer , Please restart it locally by running the following command :
dfx start --backgroundOpen the browser and navigate to
dfx.jsonAddress and port number specified in the configuration file .By default ,
localThe network is bound to127.0.0.1:8000Address and port number .canisterIdtakedfx canister idThe required parameters returned by the command and Candid UI The container identifier is added to URL.for example , complete URL It should be similar to the following , But with
CANDID-UI-CANISTER-IDENTIFIERfromdfx canister idCommand returned :http://127.0.0.1:8000/?canisterId=<CANDID-UI-CANISTER-IDENTIFIER>The browser will display a form , Allows you to specify a container identifier or select Candid describe (
.did) file .If you are not sure which container identifier to use , You can run this
dfx canister idCommand to find the identifier for a specific container name .stay Provide containers ID Field to specify the container identifier or description file for your application , And then click go to To display the service description .
View the list of function calls and types defined in the program .
Type the appropriate type of value for the function , Or click “** Random ”** Production value , And then click “** call ”** or “** Inquire about ”** To see the results .
Please note that , According to the type of data ,Candid The interface may display additional configuration settings for testing functions . for example , If the function accepts an array , You may need to specify the number of items in the array before entering a value .
In this case , Each function accepts an array of text strings . therefore , You first select the length of the array , Then click Call Previously set values for each item .

Stop the local network
After you have finished testing the program , You can stop local Internet computer network , So that it will not continue to run in the background .
To stop the local network :
In the terminal that displays the network operation , Press Control-C Interruptible local network processes .
Stop... By running the following command Internet computer network :
dfx stop
Add a natural number
In this tutorial , You will write a program to create a single participant and provide some basic functions to increment the counter and explain the persistence of the value .
In this tutorial , The role name is Counter. The program uses this currentValue Variable to contain a natural number representing the current value of the counter . The program supports the following function calls :
- The
incrementFunction call to update the current value , from 1( No return value ) Increasing . - The
getThe function call queries and returns the current value . - The
setThe function call updates the current value to any value you specify as a parameter .
This tutorial provides a simple example , Shows how to increment a counter by calling a function on a deployed container . Increase a value by calling the function multiple times , You can verify variable status ( That is, the variable value between two calls ) Whether it persists .
Before you start
Before you start this tutorial , Please verify the following :
- You have downloaded and installed DFINITY Canister SDK package ..
- You have stopped any... Running on the local computer Internet Computer network processes .
Completing this tutorial takes approximately 20 minute .
Create a new project
To create a new project directory for this tutorial :
If you haven't opened , Please open a terminal shell on the local computer .
If you are using Internet Computer project , Please switch to the one you use for Internet Folder for computer projects .
Create a new project by running the following command :
dfx new my_counterThis command
my_counterCreate a new project and... For your project Git The repository .Switch to your project directory by running the following command :
cd my_counter
Modify default configuration
You've seen , Creating a new project adds a default dfx.json To your project directory . In this tutorial , You will modify the default settings , Use different names in your project main program .
Change the default dfx.json The configuration file :
open
dfx.jsonIn the text editor configuration file , Change defaultmainSet upmain.moCome onincrement_counter.mo.for example :
"main": "src/my_counter/increment_counter.mo",For this tutorial , Change the name of the source file from
main.moChange toincrement_counter.moDescription onlydfx.jsonHow the settings in the configuration file determine the source file to compile .In more complex applications , You may have multiple source files with dependencies , You need to use
dfx.jsonConfiguration file to manage these dependencies . In such a scenario —— In yourdfx.jsonMultiple containers and programs are defined in the file —— Name multiple files at the same timemain.moIt can be confusing .You can leave the rest of the default settings .
Save your changes and close
dfx.jsonFile to continue .dfx.jsonChange the name of the main program file in the source code directory to match the name specified in the configuration file by running the following commandmv src/my_counter/main.mo src/my_counter/increment_counter.mo
Modify the default program
up to now , You only changed the name of the project's main program . The next step is to modify the code src/my_counter/increment_counter.mo The file defines an actor Counter And implement increment,get as well as set function .
Modify the default template source code :
if necessary , Please check if you are still in the project directory .
src/my_counter/increment_counter.moOpen the file in a text editor and delete the existing contents .Copy and paste the following sample code into
increment_counter.moIn file :// Create a simple Counter actor. actor Counter { stable var currentValue : Nat = 0; // Increment the counter with the increment function. public func increment() : async () { currentValue += 1; }; // Read the counter value with a get function. public query func get() : async Nat { currentValue }; // Write an arbitrary value with a set function. public func set(n: Nat) : async () { currentValue := n; }; }running
Let's take a closer look at the sample program :
You can see
currentValueThe variable declaration in this example containsstableKeywords used to indicate status —— You can set 、 Incrementing and retrieving values —— remain unchanged .This keyword ensures that the value of a variable does not change when the program is upgraded .
currentValueThe declaration of a variable also specifies that its type is natural (Nat) Count .The program includes two common update methods ——the
incrementandsetfunction —— And a query method , In this casegetfunction .
Save your changes and close the file to continue .
Start the local network
In the build my_counter Before the project , You need to connect to Internet computer network , Or run it locally in your development environment , Or run remotely on a subnet that you can access .
Starting the network locally requires a dfx.json file , So you should make sure that you are in the root directory of the project . For this tutorial , You should have two separate terminal housings , So that you can start and view network operations in a terminal , And manage your project in another terminal .
Start the network locally :
Open a new terminal window or tab on the local computer .
If necessary, , Navigate to the root directory of the project .
- You should now open Two terminals .
- You should Project directory As you Current working directory .
Start on the local computer by running the following command Internet computer network :
dfx startAfter starting the local network , The terminal displays messages about network operation .
Keep the terminal displaying network operation open , And switch the focus to the original terminal where you created the new project .
register 、 Build and deploy applications
Before you connect to a that runs locally in your development environment Internet After the computer network , You can register locally 、 Build and deploy your application .
Deploy the application locally :
if necessary , Please check that you are still in the root directory of the project .
Register by running the following command 、 Build and deploy your application :
dfx deployOf
dfx deployOutput display information about the operation it performs .
Call methods on deployed containers
After successfully deploying the container , You can simulate the end user invoking the methods provided by the container . In this tutorial , You will call a get Method to query the value of the counter , One increment Increments the... Of the counter on each call set Method , And a method that passes parameters to update the counter to any value you specify .
To test the calling method on the deployed container :
Run the following command to invoke the
getfunction , This function readscurrentValueThe current value of the variable on the deployed container :dfx canister call my_counter getThe order will
currentValueThe current value of the variable returns zero :(0)Run the following command to invoke
incrementFunction willcurrentValueThe value of the variable on the deployed container plus 1:dfx canister call my_counter incrementThis command increases the value of the variable —— Change its state —— But no result is returned .
Rerun the following command to get
currentValueThe current value of the variable on the deployed container :dfx canister call my_counter getThe order will
currentValueThe updated value of the variable is returned as 1:(1)Run other commands to try calling other methods and using different values .
for example , Try a command like the following to set and return the counter value :
dfx canister call my_counter set '(987)' dfx canister call my_counter getreturn 987 The current value of the .
dfx canister call my_counter increment dfx canister call my_counter getreturn 988 The incremental value of .
Test functions in the browser
Container interface description language ( Often referred to as Candid Or more generally called IDL) Provides a common language for specifying container service signatures .Candid It provides you with a unified way to interact with containers written in different languages or accessed with different tools . for example , Whether the underlying program is native Rust、JavaScript still Motoko,Candid Both provide a consistent view of services .Candid Different tools are also supported ( for example dfx Command line interface and network neural system application ) To share a common description of the service .
be based on actor Type signature of ,Candid One is also provided Web Interface , Allows you to call container functions for testing and debugging .
Use dfx deployordfx canister install Command after the project is deployed locally , You can access... In your browser Candid Web Interface endpoint . This Web Interface (Candid UI) Expose the service description in a form , Enables you to quickly view and test functions and try to enter different data types , Without writing any front-end code .
To use Candid Web Interface to test container functions :
Use
dfx canister id __Candid_UICommand to find the Candid UI Container Identifier .dfx canister id __Candid_UIThe command shows Candid UI Container identifier for , The output is similar to the following :
r7inp-6aaaa-aaaaa-aaabq-caiCopy Candid UI Container Identifier , So that it is available on the clipboard .
If you have stopped Internet Computer , Please restart it locally by running the following command :
dfx start --backgroundOpen the browser and navigate to
dfx.jsonAddress and port number specified in the configuration file .By default ,
localThe network is bound to127.0.0.1:8000Address and port number .canisterIdtakedfx canister idThe required parameters returned by the command and Candid UI The container identifier is added to URL.for example , complete URL It should be similar to the following , But with
CANDID-UI-CANISTER-IDENTIFIERfromdfx canister idCommand returned :http://127.0.0.1:8000/?canisterId=<CANDID-UI-CANISTER-IDENTIFIER>The browser will display a form , Allows you to specify a container identifier or select Candid describe (
.did) file .If you are not sure which container identifier to use , You can run this
dfx canister idCommand to find the identifier for a specific container name .stay Provide containers ID Field to specify the container identifier or description file for your application , And then click go to To display the service description .
View the list of function calls and types defined in the program .
Type the appropriate type of value for the function , Or click “** Random ”** Production value , And then click “** call ”** or “** Inquire about ”** To see the results .
Please note that , According to the type of data ,Candid The interface may display additional configuration settings for testing functions . for example , If the function accepts an array , You may need to specify the number of items in the array before entering a value .

Stop the local network
After you have finished testing the program , You can stop local Internet computer network , So that it will not continue to run in the background .
To stop the local network :
In the terminal that displays the network operation , Press Control-C Interruptible local network processes .
Stop... By running the following command Internet computer network :
dfx stop
Use integers in calculator functions
In this tutorial , You will write a simple calculator program , This program creates a single... With multiple common entry point functions actor, To perform basic arithmetic operations .
In this tutorial , The role name is Calc. The program uses this cell The variable contains an integer , Represents the current result of a calculator operation .
The program supports the following function calls :
- Of
addFunction calls accept input and perform addition . - Of
subThe function call accepts input and performs subtraction . - Of
mulFunction calls accept input , And perform multiplication . - Of
divFunction calls accept input and perform division . - The
clearallFunction cleanupcellA value stored as a result of a previous operation , Will becellThe value is reset to zero .
The div The function also includes code that prevents the program from trying to divide by zero .
Before you start
Before you start this tutorial , Please verify the following :
- You have downloaded and installed DFINITY Canister SDK package
- You have stopped any... Running on the local computer Internet Computer network processes .
Completing this tutorial takes approximately 20 minute .
Create a new project
To create a new project for this tutorial :
If you haven't opened , Please open a terminal shell on the local computer .
If you are using Internet Computer project , Please switch to the one you use for Internet Folder for computer projects .
Create a new project by running the following command :
dfx new calcSwitch to your project directory by running the following command :
cd calc
Modify default configuration
In this tutorial , Let's change the default dfx.json The configuration file , Use a more specific name for its main program .
Change the default dfx.json The configuration file :
dfx.jsonOpen the configuration file in a text editor .take
mainThe key settings are changed from the defaultmain.moThe program name is changed tocalc_main.mo.for example :
"main": "src/calc/calc_main.mo"For this tutorial , Change the name of the source file from
main.moChange tocalc_main.moDescription onlydfx.jsonHow the settings in the configuration file determine the source file to compile .In more complex applications , You may have multiple source files instead of a single
mainProgram files . More complex applications may also have specific dependencies between multiple source files , You need to usedfx.jsonConfigure the settings in the file to manage these source files . In such a scenario —— In yourdfx.jsonMultiple containers and programs are defined in the file —— Name all the filesmain.moIt may make navigation in your workspace more difficult . The name you choose for each program does not matter , But the important thing is that you aredfx.jsonThe name set in the file matches the name of the program in the file system .Save your changes and close the file to continue .
Modify the default program
For this tutorial , You need to replace the default program with a program that performs basic arithmetic operations .
Replace the default program :
if necessary , Please check if you are still in the project directory .
Copy template
main.moFile to create acalc_main.moName the new file by running the following command :cp src/calc/main.mo src/calc/calc_main.mosrc/calc/calc_main.moOpen the file in a text editor and delete the existing contents .Copy and paste the following sample code into
calc_main.moIn file :// This single-cell calculator defines one calculator instruction per // public entry point (add, sub, mul, div). // Create a simple Calc actor. actor Calc { var cell : Int = 0; // Define functions to add, subtract, multiply, and divide public func add(n:Int) : async Int { cell += n; cell }; public func sub(n:Int) : async Int { cell -= n; cell }; public func mul(n:Int) : async Int { cell *= n; cell }; public func div(n:Int) : async ?Int { if ( n == 0 ) { return null // null indicates div-by-zero error } else { cell /= n; ?cell } }; // Clear the calculator and reset to zero public func clearall() : async Int { if (cell : Int != 0) cell -= cell; return cell }; };You may notice that this sample code uses integers (
Int) data type , Enables you to use positive or negative numbers . If you want to limit the functions in this calculator code to only positive numbers , You can change the data type to allow only natural (Nat) data .Save your changes and close the file to continue .
Start the local network
In the build calc Before the project , You need to connect to Internet computer network , Or run it locally in your development environment , Or run remotely on a subnet that you can access .
Starting the network locally requires a dfx.json file , So you should make sure that you are in the root directory of the project . For this tutorial , You should have two separate terminal housings , So that you can start and view network operations in a terminal , And manage your project in another terminal .
Start the network locally :
Open a new terminal window or tab on the local computer .
If necessary, , Navigate to the root directory of the project .
- You should now open Two terminals .
- You should Project directory As you Current working directory .
Start on the local computer by running the following command Internet computer network :
dfx startAfter starting the local network , The terminal displays messages about network operation .
Keep the terminal displaying network operation open , And switch the focus to the original terminal where you created the new project .
register 、 Build and deploy applications
Before you connect to a that runs locally in your development environment Internet After the computer network , You can register locally 、 Build and deploy your application .
Deploy the application locally :
if necessary , Please check that you are still in the root directory of the project .
Register by running the following command 、 Build and deploy your application :
dfx deployOf
dfx deployOutput display information about the operation it performs .
Verify the calculator function on the container
You have now deployed the program locally Internet On the computer network Containers . You can use dfx canister call Command to test the program .
To test your deployed programs :
Use this
dfx canister callCommand invocationcalcContainersaddAnd through the function10Run the following command to pass input parameters to it :dfx canister call calc add '(10)'When you pass a parameter enclosed in single quotes and parentheses , Interface description language (IDL) Will resolve parameter types , So you don't have to specify the parameter type manually .
The validation command returns
addExpected value of the function . for example , The program displays output similar to the following :(10)Call this... By running the following command
mulFunction and pass input parameters to it3:dfx canister call calc mul '(3)'The validation command returns
mulExpected value of the function . for example , The program displays output similar to the following :(30)Call this... By running the following command
subFunction and will5type The input parameters of the are passed to itnumber:dfx canister call calc sub '(5)'The validation command returns
subExpected value of the function . for example , The program displays output similar to the following :(25)Call this... By running the following command
divFunction and pass input parameters to it5:dfx canister call calc div '(5)'The validation command returns
divExpected value of the function . for example , The program displays output similar to the following :( Options 5)You may notice that
divFunction returns an optional result . The program makes the result optional , In order todivfunctionnullReturns... In case of division by zero error .Because the cell variable in this program is an integer , You can also call its function and specify a negative input value . for example , You can run the following command :
dfx canister call calc mul '(-4)' Copyreturn :
(-20)Call the
clearallFunction and verify that it willcellThe value is reset to zero :dfx canister call calc clearallfor example , The program displays output similar to the following :
(0)
Test functions in the browser
Container interface description language ( Often referred to as Candid Or more generally called IDL) Provides a common language for specifying container service signatures .Candid It provides you with a unified way to interact with containers written in different languages or accessed with different tools . for example , Whether the underlying program is native Rust、JavaScript still Motoko,Candid Both provide a consistent view of services .Candid Different tools are also supported ( for example dfx Command line interface and network neural system application ) To share a common description of the service .
be based on actor Type signature of ,Candid One is also provided Web Interface , Allows you to call container functions for testing and debugging .
Use dfx deployordfx canister install Command after the project is deployed locally , You can access... In your browser Candid Web Interface endpoint . This Web Interface (Candid UI) Expose the service description in a form , Enables you to quickly view and test functions and try to enter different data types , Without writing any front-end code .
To use Candid Web Interface to test container functions :
Use
dfx canister id __Candid_UICommand to find the Candid UI Container Identifier .dfx canister id __Candid_UIThe command shows Candid UI Container identifier for , The output is similar to the following :
r7inp-6aaaa-aaaaa-aaabq-caiCopy Candid UI Container Identifier , So that it is available on the clipboard .
If you have stopped Internet Computer , Please restart it locally by running the following command :
dfx start --backgroundOpen the browser and navigate to
dfx.jsonAddress and port number specified in the configuration file .By default ,
localThe network is bound to127.0.0.1:8000Address and port number .canisterIdtakedfx canister idThe required parameters returned by the command and Candid UI The container identifier is added to URL.for example , complete URL It should be similar to the following , But with
CANDID-UI-CANISTER-IDENTIFIERfromdfx canister idCommand returned :http://127.0.0.1:8000/?canisterId=<CANDID-UI-CANISTER-IDENTIFIER>The browser will display a form , Allows you to specify a container identifier or select Candid describe (
.did) file .If you are not sure which container identifier to use , You can run this
dfx canister idCommand to find the identifier for a specific container name .stay Provide containers ID Field to specify the container identifier or description file for your application , And then click go to To display the service description .
View the list of function calls and types defined in the program .
Type the appropriate type of value for the function , Or click “** Random ”** Production value , And then click “** call ”** or “** Inquire about ”** To see the results .
Please note that , According to the type of data ,Candid The interface may display additional configuration settings for testing functions . for example , If the function accepts an array , You may need to specify the number of items in the array before entering a value .

Stop the local network
After you have finished testing the program , You can stop local Internet computer network , So that it will not continue to run in the background .
To stop the local network :
In the terminal that displays the network operation , Press Control-C Interruptible local network processes .
Stop... By running the following command Internet computer network :
dfx stop
Import library module
In this tutorial , You will write a simple program , Enables you to store and find phone numbers . This tutorial explains how to import and use some basic Motoko Library function .
In this tutorial ,Motoko The basic library functions are in List and AssocList Defined in module , Enables you to process lists as linked key value pairs . In this example , key yes a name, value yes phone The text string associated with the name .
The program supports the following function calls :
- The
insertFunction acceptancenameandphoneKey value pairs are stored asbookInput in variable . - The
lookupThe function is a query , It uses the specifiednameKey as input to find the associated phone number .
Before you start
Before you start this tutorial , Please verify the following :
- You have downloaded and installed DFINITY Canister SDK package
- You have stopped any... Running on the local computer Internet Computer network processes .
Completing this tutorial takes approximately 10 minute .
Create a new project
To create a new project for this tutorial :
If you haven't opened , Please open a terminal shell on the local computer .
If you are using Internet Computer project , Please switch to the one you use for Internet Folder for computer projects .
Create a new project by running the following command :
dfx new phonebookSwitch to your project directory by running the following command :
cd phonebook
Modify the default program
In this tutorial , Let us main.mo Create a new file for a simple phone number Finder .
Modify the default template :
src/phonebook/main.moOpen the file in a text editor and delete the existing contents .Copy and paste the following sample code into
main.moIn file :// Import standard library functions for lists import L "mo:base/List"; import A "mo:base/AssocList"; // The PhoneBook actor. actor { // Type aliases make the rest of the code easier to read. public type Name = Text; public type Phone = Text; // The actor maps names to phone numbers. flexible var book: A.AssocList<Name, Phone> = L.nil<(Name, Phone)>(); // An auxiliary function checks whether two names are equal. func nameEq(l: Name, r: Name): Bool { return l == r; }; // A shared invokable function that inserts a new entry // into the phone book or replaces the previous one. public func insert(name: Name, phone: Phone): async () { let (newBook, _) = A.replace<Name, Phone>(book, name, nameEq, ?phone); book := newBook; }; // A shared read-only query function that returns the (optional) // phone number corresponding to the person with the given name. public query func lookup(name: Name): async ?Phone { return A.find<Name, Phone>(book, name, nameEq); }; };When viewing this sample program , You may notice the following key elements :
- Code definition
NameandPhoneAs a custom text type . Creating user-defined types improves code readability . - The
insertThe function is an update call , ThelookupThe function is a query call . PhoneUse?PhoneThe syntax identifies the type as an optional value .
- Code definition
Start the local network
In the build phonebook Before the project , You need to connect to Internet computer network , Or run it locally in your development environment , Or run remotely on a subnet that you can access .
Starting the network locally requires a dfx.json file , So you should make sure that you are in the root directory of the project . For this tutorial , You should have two separate terminal housings , So that you can start and view network operations in a terminal , And manage your project in another terminal .
Start the network locally :
Open a new terminal window or tab on the local computer .
If necessary, , Navigate to the root directory of the project .
- You should now open Two terminals .
- You should Project directory As you Current working directory .
Start on the local computer by running the following command Internet computer network :
dfx start --cleanIn this tutorial , We use the
--cleanOption starts in a clean state Internet computer network .This option removes any orphaned daemon or container identifiers that may interrupt normal operation . for example , If you
dfx stopForgot to send... When moving between items a , There may be a process running in the background or in another terminal . The--cleanOption ensures that you can start Internet Computer network and continue to the next step , There is no need to manually find and terminate any running processes .Keep the terminal displaying network operation open , And switch the focus to the original terminal where you created the new project .
register 、 Build and deploy applications
Before you connect to a that runs locally in your development environment Internet After the computer network , You can register locally 、 Build and deploy your application .
Deploy the application locally :
if necessary , Please check that you are still in the root directory of the project .
Register by running the following command 、 Build and deploy your application :
dfx deploy phonebookThe
dfx.jsonThe file provides entry points for creating application front ends andassetsDefault settings for containers .In the previous tutorial , We deleted the entry for the asset container , Because we didn't add a front end for the sample application . By eliminating unused files , This change keeps our project workspace clean . however , There is no requirement to do so , And leave the asset container description in
dfx.jsonThere is no harm in the document . for example , If you plan to add front-end assets later , You might want to use it as a placeholder .For this tutorial , You can use the
dfx deploy phonebookThe command deploys only the phonebook backend container , Because the project is a terminal based application , Does not include any front-end assets .Add name and number
You have now deployed the program as... On the local replica network Containers , And you can use dfx canister call Command to test your program .
To test your application deployed on the local replica network :
Use this
dfx canister callcommandphonebookUse thisinsertFunction call container , And pass the name and phone number to it by running the following command :dfx canister call phonebook insert '("Chris Lynn", "01 415 792 1333")'Add a second name and number pair by running the following command :
dfx canister call phonebook insert '("Maya Garcia", "01 408 395 7276")'lookupBy running the following command , Verify that the command uses this function to return and “Chris Lynn” Associated number :dfx canister call phonebook lookup '("Chris Lynn")'This command returns output similar to the following :
(opt "01 415 792 1333")lookupBy running the following command , Try to use with “Maya Garcia” The associated number calls the function :dfx canister call phonebook lookup '("01 408 395 7276")'Please note that , under these circumstances , The command returns ,
(null)Because the phone number is not the same as “Maya Garcia” Name the key associated with the entry .Try
lookupCall this function again by running the following command to return “Maya Garcia” and “Chris Lynn” The phone number of :dfx canister call phonebook lookup '("Maya Garcia","Chris Lynn")'Because the program is written to return a value for a key , So this command only returns the information associated with the first key , In this case The phone number of
Maya Garcia.
Test functions in the browser
Container interface description language ( Often referred to as Candid Or more generally called IDL) Provides a common language for specifying container service signatures .Candid It provides you with a unified way to interact with containers written in different languages or accessed with different tools . for example , Whether the underlying program is native Rust、JavaScript still Motoko,Candid Both provide a consistent view of services .Candid Different tools are also supported ( for example dfx Command line interface and network neural system application ) To share a common description of the service .
be based on actor Type signature of ,Candid One is also provided Web Interface , Allows you to call container functions for testing and debugging .
Use dfx deployordfx canister install Command after the project is deployed locally , You can access... In your browser Candid Web Interface endpoint . This Web Interface (Candid UI) Expose the service description in a form , Enables you to quickly view and test functions and try to enter different data types , Without writing any front-end code .
To use Candid Web Interface to test container functions :
Use
dfx canister id __Candid_UICommand to find the Candid UI Container Identifier .dfx canister id __Candid_UIThe command shows Candid UI Container identifier for , The output is similar to the following :
r7inp-6aaaa-aaaaa-aaabq-caiCopy Candid UI Container Identifier , So that it is available on the clipboard .
If you have stopped Internet Computer , Please restart it locally by running the following command :
dfx start --backgroundOpen the browser and navigate to
dfx.jsonAddress and port number specified in the configuration file .By default ,
localThe network is bound to127.0.0.1:8000Address and port number .canisterIdtakedfx canister idThe required parameters returned by the command and Candid UI The container identifier is added to URL.for example , complete URL It should be similar to the following , But with
CANDID-UI-CANISTER-IDENTIFIERfromdfx canister idCommand returned :http://127.0.0.1:8000/?canisterId=<CANDID-UI-CANISTER-IDENTIFIER>The browser will display a form , Allows you to specify a container identifier or select Candid describe (
.did) file .If you are not sure which container identifier to use , You can run this
dfx canister idCommand to find the identifier for a specific container name .stay Provide containers ID Field to specify the container identifier or description file for your application , And then click go to To display the service description .
View the list of function calls and types defined in the program .
Type the appropriate type of value for the function , Or click “** Random ”** Production value , And then click “** call ”** or “** Inquire about ”** To see the results .
Please note that , According to the type of data ,Candid The interface may display additional configuration settings for testing functions . for example , If the function accepts an array , You may need to specify the number of items in the array before entering a value .

Modify the source code in the program
To extend what you have learned in this tutorial , You may want to try to modify the source code to return different results .
for example , You may want to change the source code , Instead of inserting and finding the current key value ( full name - Telephone ) To create a program , The program store is similar to a database “ Record ” Contact information for , One of the primary keys is associated with multiple fields . In this example , Your program may allow users or other programs to add information ( For example, home phone number 、 Phone number 、 E-mail address and street address ), And selectively return all or specific field values .
Stop the local network
After you have finished testing the program , You can stop local Internet computer network , So that it will not continue to run in the background .
To stop the local network :
In the terminal that displays the network operation , Press Control-C Interruptible local network processes .
Stop... By running the following command Internet computer network :
dfx stop
The use of multiple actor
In this tutorial , You will create a project with multiple roles . at present , You can only be in Motoko Define a actor, And single actor Always compile as a single container . however , You can create... With multiple roles project , And from the same dfx.json Configuration files build multiple containers .
In this tutorial , You will create separate program files for three actors in the same project . The project defines the following unrelated participants :
The
assistantActors provide functions to add and perform tasks in the to-do list .For the sake of simplicity , The code examples in this tutorial only include the ability to add to-do items and display the list of currently added to-do items . A more complete version of this program - With additional functionality for marking items as complete and deleting items from the list - stay Example In the repository as Simple to-do checklist Provide .
The
rock_paper_scissorsThe actor provided a hard coded stone , Scissors , Cloth's game determines the function of a winner .This code example demonstrates the basic use of
switchandcaseWith hard coded players and select a meta subroutine .The
daemonActors provide simulation functions , Start and stop daemons .This code example simply assigns a variable and prints a message for demonstration purposes
Before you start
Before you start this tutorial , Please verify the following :
- You have downloaded and installed DFINITY Canister SDK package
- You have stopped any... Running on the local computer Internet Computer network processes .
Completing this tutorial takes approximately 20 minute .
Create a new project
To create a new project for this tutorial :
If you haven't opened , Please open a terminal shell on the local computer .
If you are using Internet Computer project , Please switch to the one you use for Internet Folder for computer projects .
Create a new project by running the following command :
dfx new multiple_actorsSwitch to your project directory by running the following command :
cd multiple_actors
Modify default configuration
You've seen , Creating a new project adds a default dfx.json To your project directory . For this tutorial , You need to add sections to this file to specify the location of each program that defines the actor you want to build .
Change the default dfx.json The configuration file :
dfx.jsonOpen the configuration file in a text editor , Then the default ismultiple_actorsThe container name and source directory are changed toassistant.for example , stay
canistersKey down :"assistant": { "main": "src/assistant/main.mo", "type": "motoko" }Because you want to
canistersAdd settings to this section of the configuration file , You must also add a... After the curly braces that contain the location of the main source file and the container type commaassistant.multiple_actors_assetsDelete this section from the file .Add a new container name to the program 、 Source code location and container type
rock_paper_scissors, And define... For the containerdaemonAdd a new container name to the program file below 、 Source code location and container typeassistant.After making changes , file
canisterspartdfx.jsonShould be similar to the following :{ "canisters": { "assistant": { "main": "src/assistant/main.mo", "type": "motoko" }, "rock_paper_scissors": { "main": "src/rock_paper_scissors/main.mo", "type": "motoko" }, "daemon": { "main": "src/daemon/main.mo", "type": "motoko" } }, "defaults": { "build": { "packtool": "" } }, "dfx": "0.7.2", "networks": { "local": { "bind": "127.0.0.1:8000", "type": "ephemeral" } }, "version": 1 }You can leave the rest as is .
Save your changes and close
dfx.jsonFile to continue .dfx.jsonBy running the following command , Change the name of the default source file directory to match the name specified in the configuration file :cp -r src/multiple_actors/ src/assistant/Copy... By running the following command
assistantSource file directory to createrock_paper_scissorsactor Main program file :cp -r src/assistant/ src/rock_paper_scissors/Copy... By running the following command
assistantSource file directory to createdaemonactor Main program file :cp -r src/assistant/ src/daemon/
Modify the default program
You now have three separate in the directory src Catalog , Each directory has a template main.mo file . In this tutorial , You will main.mo Replace the contents of each template file with different participants .
Modify the default source code :
src/assistant/main.moOpen the file in a text editor and delete the existing contents .Copy and paste the following sample code into a file :
import Array "mo:base/Array"; import Nat "mo:base/Nat"; // Define the actor actor Assistant { stable var todos : [ToDo] = []; stable var nextId : Nat = 1; // Define to-do item properties type ToDo = { id : Nat; description : Text; completed : Bool; }; // Add to-do item utility func add(todos : [ToDo], description : Text, id : Nat) : [ToDo] { let todo : ToDo = { id = id; description = description; completed = false; }; Array.append(todos, [todo]) }; // Show to-do item utility func show(todos : [ToDo]) : Text { var output : Text = "\n___TO-DOs___"; for (todo : ToDo in todos.vals()) { output #= "\n(" # Nat.toText(todo.id) # ") " # todo.description; if (todo.completed) { output #= " "; }; }; output }; public func addTodo (description : Text) : async () { todos := add(todos, description, nextId); nextId += 1; }; public query func showTodos () : async Text { show(todos) }; };Save your changes and close
main.moFile to continue .src/rock_paper_scissors/main.moOpen the file in a text editor and delete the existing contents .Copy and paste the following sample code into a file :
import I "mo:base/Iter"; actor RockPaperScissors { stable var alice_score : Nat = 0; stable var bob_score : Nat = 0; stable var alice_last : Choice = #scissors; stable var bob_last : Choice = #rock; type Choice = { #rock; #paper; #scissors; }; public func contest() : async Text { for (i in I.range(0, 99)) { battle_round(); }; var winner = "The contest was a draw"; if (alice_score > bob_score) winner := "Alice won" else if (alice_score < bob_score) winner := "Bob won"; return (winner); }; func battle_round() : () { let a = alice(bob_last); let b = bob(alice_last); switch (a, b) { case (#rock, #scissors) alice_score += 1; case (#rock, #paper) bob_score += 1; case (#paper, #scissors) alice_score += 1; case (#paper, #rock) bob_score += 1; case (#scissors, #paper) alice_score += 1; case (#scissors, #rock) bob_score += 1; case (#rock, #rock) alice_score += 0; case (#paper, #paper) bob_score += 0; case (#scissors, #scissors) alice_score += 0; }; alice_last := a; bob_last := b; return (); }; // Hard-coded players and choices func bob(last : Choice) : Choice { return #paper; }; func alice(last : Choice) : Choice { return #rock; }; };Save your changes and close
main.moFile to continue .src/daemon/main.moOpen the file in a text editor and delete the existing contents .Copy and paste the following sample code into a file :
actor Daemon { stable var running = false; public func launch() : async Text { running := true; debug_show "The daemon process is running"; }; public func stop(): async Text { running := false; debug_show "The daemon is stopped"; }; };Save your changes and close
main.moFile to continue .
Start the local network
In the build multiple_actors Before the project , You need to connect to Internet computer network , Or run it locally in your development environment , Or run remotely on a subnet that you can access .
Start the network locally :
Open a new terminal window or tab on the local computer .
If necessary, , Navigate to the root directory of the project .
Start on the local computer by running the following command Internet computer network :
dfx startKeep the terminal displaying network operation open , And switch the focus to the original terminal where you created the new project .
register 、 Build and deploy your application
Connect to... Running locally in the development environment Internet After the computer network , You can register locally 、 Build and deploy multi container applications .
Deploy the application locally :
if necessary , Please check that you are still in the root directory of the project .
Register by running the following command 、 Build and deploy applications :
dfx deployIf you have access to remotely running Internet Computer , You can specify
--networkOptions anddfx.jsonFile to deploy to the network , Instead of deploying locally . for example , If you want to connect to... Specified by the network alias URL,icYou will run a command similar to the following :dfx deploy --network icOf
dfx deployOutput display information about the operation it performs . for example , The command showsdfx.jsonNetwork specific container identifiers for the three containers defined in the configuration file .Deploying all canisters. Creating canisters... Creating canister "assistant"... "assistant" canister created with canister id: "75hes-oqbaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q" Creating canister "daemon"... "daemon" canister created with canister id: "cxeji-wacaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q" Creating canister "rock_paper_scissors"... "rock_paper_scissors" canister created with canister id: "7kncf-oidaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q"
Verify the deployment by calling the function
You have now deployed three programs as... On the local replica network Containers , And you can use dfx canister call Command to test each program .
To test your deployed programs :
Use this
dfx canister callcommandassistantUse thisaddTodoFunction call container , And pass the task to be added to it by running the following command :dfx canister call assistant addTodo '("Schedule monthly demos")'showTodosBy running the following command , Verify that the command returns a to-do list item using this function :dfx canister call assistant showTodosThis command returns output similar to the following :
(" ___TO-DOs___ (1) Schedule monthly demos")By running the following command , Use this
dfx canister callCommand invocationrock_paper_scissorsUse thiscontestContainer of a function :dfx canister call rock_paper_scissors contestThis command returns the result of a hard coded contest similar to the following :
("Bob won")By running the following command , Use this
dfx canister callCommand invocationdaemonUse thislaunchContainer of a function :dfx canister call daemon launchVerify simulation
launchThe function returns “ The daemon is running ” news ”:(""The daemon process is running"")
Stop the local network
After you have finished testing the program , You can stop local Internet computer network , So that it will not continue to run in the background .
To stop the local network :
In the terminal that displays the network operation , Press Control-C Interruptible local network processes .
Stop... By running the following command Internet computer network :
dfx stop
Custom front end
Now that you know how to create 、 A basic understanding of building and deploying simple programs , And be familiar with the default project file and the sample front end , You may want to start trying different ways to customize the front-end user experience for your project .
This tutorial demonstrates how to use the simple React The framework creates a new front end for the default sample program , And guide you through some basic modifications to customize the displayed interface . Later tutorials will extend the techniques introduced here , But if you already know how to use CSS、HTML、JavaScript and React Or other frameworks to build your user interface , You can skip this tutorial .
This tutorial explains how to use React Framework to manage the container's document object model (DOM). because React Have their own custom DOM grammar , So it needs to be modified webpack Configure to compile front-end code , The front-end code uses JSX Compiling . About learning to use React and JSX For more information , see also React Website Upper introduction .
Before you start
Before you start this tutorial , Please verify the following :
- You have
node.jsInstall for front-end development , And you can installnpm installPackages used in your project . About installing for the local operating system and package manager node Information about , see also Node Website . - You have downloaded and installed DFINITY Canister SDK package
- If you use Visual Studio Code As IDE, You have made a reservation for Motoko Installed Visual Studio Code plug-in unit .
- You have stopped any... Running on the local computer Internet Computer network processes .
Completing this tutorial takes approximately 30 minute .
Create a new project
Create a new project directory for your custom front-end application :
If you haven't opened , Please open a terminal shell on the local computer .
If you are using Internet Computer project , Please switch to the one you use for Internet Folder for computer projects .
node.jsCheck that you have installed... Locally by running the following command :which node which npmIf you haven't
node.jsinstall , You should download and install it first , And then go on to the next step . About installing for the local operating system and package manager node Information about , see also Node Website .Create a new project by running the following command :
dfx new custom_greetingThe
dfx new custom_greetingCommand to create a newcustom_greetingproject .Switch to your project directory by running the following command :
cd custom_greeting
install React frame
If you have never used it before React, So before editing the front-end code , You may want to browse React Tutorial or React Website .
To install the required frame modules :
Install... By running the following command React modular :
npm install --save react react-domInstall the required by running the following command TypeScript Language compiler loader :
npm install --save typescript ts-loader Copy
{ "name": "custom_greeting_assets", "version": "0.1.0", "description": "", "keywords": [], "scripts": { "build": "webpack" }, "devDependencies": { "@dfinity/agent": "0.7.2", "assert": "2.0.0", "buffer": "6.0.3", "events": "3.3.0", "html-webpack-plugin": "5.3.1", "process": "0.11.10", "stream-browserify": "3.0.0", "terser-webpack-plugin": "5.1.1", "util": "0.12.3", "webpack": "5.24.4", "webpack-cli": "4.5.0" }, "dependencies": { "react": "^17.0.2", "react-dom": "^17.0.2", "ts-loader": "^8.1.0", "typescript": "^4.2.4" } }
View default configuration
Before we use for this tutorial React Before making any changes , Let's review dfx.json Default front end settings in your project's configuration file .
Check the default dfx.json The configuration file :
dfx.jsonOpen the configuration file in a text editor .Please note that , The
canistersKey containscustom_greeting_assetsContainer settings .{ "canisters": { ... "custom_greeting_assets": { "dependencies": [ "custom_greeting" ], "frontend": { "entrypoint": "src/custom_greeting_assets/src/index.html" }, "source": [ "src/custom_greeting_assets/assets", "dist/custom_greeting_assets/" ], "type": "assets" } } }Let's look at the settings in this section .
- The front-end assets of the project are compiled into their own containers , In this case , be known as
custom_greeting_assets. - By default, the asset container depends on the main container of the project .
- The
frontend.entrypointSet the specifiedindex.htmlFile to be used as the entry point for the application ( In this case, the file ) The path of . If you have a different starting point ( for example , Customizefirst-page.htmlfile ), You are about to modify this setting . - these
sourceSettings specify yoursrcanddistPath to directory . ThesrcSet the directory that specifies the static assets to include in the asset container when building the project . If you have a custom cascading style sheet (CSS) or JavaScript file , You can include them in the folder specified in this path . After building the project , The project assets will be transferred fromdistSet the specified directory to provide . - The
typeSet the specifiedcustom_greeting_assetsIt's an asset container, not a program container .
In this tutorial , We will be in
index.jsxAdd... To the file React JavaScript , But it doesn't need to be rightdfx.jsonMake any changes to the default settings in the file .- The front-end assets of the project are compiled into their own containers , In this case , be known as
close
dfx.jsonFile to continue .
View the default front-end file
For this tutorial , You will use the default main.mo Program and operate the application only by modifying the front end . however , Before making any changes , Let's first look at the contents of the project's default front-end file .
View the default front-end file :
src/custom_greeting_assets/src/index.htmlOpen the file in a text editor .This template file is the default front-end entry point for the application , By... In the file
frontend.entrypointSet the specifieddfx.json.This file contains Standards HTML, Including CSS The files and are located in
src/custom_greeting_assets/assetsA reference to an image in a directory . Defaultindex.htmlThe file also includes for displayingnameInput fields of parameters and standards of clickable buttons HTML grammar .This is with you View the default front end in notice The default front end of is the same .
src/custom_greeting_assets/src/index.jsOpen the file in a text editor .import { Actor, HttpAgent } from '@dfinity/agent'; import { idlFactory as custom_greeting_idl, canisterId as custom_greeting_id } from 'dfx-generated/custom_greeting'; const agent = new HttpAgent(); const custom_greeting = Actor.createActor(custom_greeting_idl, { agent, canisterId: custom_greeting_id }); document.getElementById("clickMeBtn").addEventListener("click", async () => { const name = document.getElementById("name").value.toString(); const greeting = await custom_greeting.greet(name); document.getElementById("greeting").innerText = greeting; });importDefaultindex.jsThe first statement in the file uses JavaScript The proxy library creates a participant and a proxy instance .- the second
importStatement forcustom_greetingTo be constructed actor Object preparation container . - The next two statements construct proxy and participant objects .
- The rest of the behavior is that the default application provides document object handling .
close
index.jsFile to continue .
Modify the front-end file
You are now ready to create a new front end for the default program .
Prepare front-end files :
webpack.config.jsopen in text editor webpack The configuration file ( ).Modify the front-end entry to replace the default
index.htmlUseindex.jsx.entry: { // The frontend.entrypoint points to the HTML file for this build, so we need // to replace the extension to `.js`. index: path.join(__dirname, info.frontend.entrypoint).replace(/\.html$/, ".jsx"), },stay
moduleThepluginsAdd the following key above the section :module: { rules: [ { test: /\.(js|ts)x?$/, loader: "ts-loader" } ] },This setting enables the program to
ts-loaderThe compiler is used for React JavaScriptindex.jsxfile . Please note that , Defaultwebpack.config.jsThere is a comment section in the file , You can modify this section to addmodulesecret key .tsconfig.jsonCreate a new file named in the root directory of your project .tsconfig.jsonOpen the file in a text editor , Then copy and paste the following into the file :{ "compilerOptions": { "target": "es2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ "lib": ["ES2018", "DOM"], /* Specify library files to be included in the compilation. */ "allowJs": true, /* Allow javascript files to be compiled. */ "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ }, "include": ["src/**/*"], }Save your changes and close
tsconfig.jsonFile to continue .src/custom_greeting_assets/src/index.jsOpen the default file in a text editor and delete the 7 To 12 That's ok .Copy and paste the following sample code into
index.jsIn file :// Insert these lines after the import statements for // importing an agent and an actor import * as React from 'react'; import { render } from 'react-dom'; // Replace the default index.js content with // React JavaScript class MyHello extends React.Component { constructor(props) { super(props); this.state = { name: 'Name', message: '', }; } async doGreet() { const greeting = await custom_greeting.greet(this.state.name); this.setState({ ...this.state, message: greeting }); } onNameChange(ev) { this.setState({ ...this.state, name: ev.target.value }); } render() { return ( <div style={ { "font-size": "30px" }}> <div style={ { "background-color": "yellow" }}> <p>Greetings, from DFINITY!</p> <p> Type your message in the Name input field, then click <b> Get Greeting</b> to display the result.</p> </div> <div style={ { "margin": "30px" }}> <input id="name" value={this.state.name} onChange={ev => this.onNameChange(ev)}></input> <button onClick={() => this.doGreet()}>Get Greeting!</button> </div> <div>Greeting is: "<span style={ { "color": "blue" }}>{this.state.message}</span>"</div> </div> ); } } render(<MyHello />, document.getElementById('app'));By running the following command, the modified
index.jsRename file toindex.jsx:mv src/custom_greeting_assets/src/index.js src/custom_greeting_assets/src/index.jsxsrc/custom_greeting_assets/src/index.htmlOpen default file in text editor , Then replace the text with<div id="app"></div>.for example :
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width"> <title>custom_greeting</title> <base href="/"> <link type="text/css" rel="stylesheet" href="main.css" /> </head> <body> <div id="app"></div> </body> </html>
Start the local network
In the build custom_greeting Before the project , You need to connect to Internet computer network , Or run it locally in your development environment , Or run remotely on a subnet that you can access .
Start the network locally :
Open a new terminal window or tab on the local computer .
If necessary, , Navigate to the root directory of the project .
Start on the local computer by running the following command Internet computer network :
dfx start --backgroundIn the local Internet After the computer network completes its startup operation , You can go on to the next step .
register 、 Build and deploy applications
Before you connect to a that runs locally in your development environment Internet After the computer network , You can register locally 、 Build and deploy your application .
Deploy the application locally :
if necessary , Please check that you are still in the root directory of the project .
Register by running the following command 、 Build and deploy your application :
dfx deploy CopyOf
dfx deployOutput display information about the operation it performs .Copy the container identifier of the container
custom_greeting_assetsTo the clipboard or notepad application .If you don't write down the container identifier , You can find it by running the following command :
dfx canister id custom_greeting_assets
View the new front end
You can now access the new front end of the default program by entering the container identifier of the asset container in the browser .
View custom front end :
Open the browser and navigate to the configuration file
localSpecified network address and port numberdfx.json.for example , If you use the default binding for the local network , Please navigate to
127.0.0.1:8000/.To specify what you want Web The server shows
canisterIdOfcustom_greeting_assetsContainers , Use the following syntax to combine parameters with The container identifier is added to URL:?canisterId=<YOUR-ASSET-CANISTER-IDENTIFIER>for example , complete URL Should be similar to the following , But when deploying containers
_canister_identifier_bycustom_greeting_assetsContainer return :http://127.0.0.1:8000/?canisterId=cxeji-wacaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-qConfirm that you are prompted to type a greeting .
for example :

Will enter... In the field Name Replace with the text you want to display , And then click Get Greeting To see the results .
for example :

Modify the front end and test your changes
After viewing the front end , You may need to make some changes .
Modify the front :
index.jsxOpen the file in a text editor and modify its style settings . for example , You may want to change the font family and use placeholders for input fields by making changes like the following :// Modify the front-end in the React JavaScript class MyHello extends React.Component { constructor(props) { super(props); this.state = { name: '', message: '', }; } async doGreet() { const greeting = await custom_greeting.greet(this.state.name); this.setState({ ...this.state, message: greeting }); } onNameChange(ev) { this.setState({ ...this.state, name: ev.target.value }); } render() { return ( <div style={ { "font-family": "sans-serif" }}> <div style={ { "font-size": "30px" }}> <p>Greetings, from DFINITY!</p> <p> Type your message in the Name input field, then click <b> Get Greeting</b> to display the result.</p> <div style={ { "margin": "30px" }}> <input id="name" placeholder="Type text here" value={this.state.name} onChange={ev => this.onNameChange(ev)}></input> <button onClick={() => this.doGreet()}>Get Greeting!</button> </div> <div>Greeting is: "<span style={ { "color": "green" }}>{this.state.message}</span>"</div> </div> </div> ); } } render(<MyHello />, document.getElementById('app'));By running the following command , Rebuild the project with your changes .
dfx buildDeploy your project changes by running the following command :
dfx canister install --all --mode reinstallBy reloading the display
custom_greeting_assetsThe container's page views the results in the browser .for example :

- Type a new message and view your new greeting . for example :

Stop the local network
After you have finished experimenting with the front end of the program , You can stop local Internet computer network , So that it will not continue to run in the background .
To stop the local network :
In the terminal that displays the network operation , Press Control-C Interruptible local network processes .
Stop... By running the following command Internet computer network :
dfx stop
Add style sheets
Cascading style sheets is one of the most common ways to customize the user experience for applications . This tutorial explains how to use React Add a style sheet when creating a new front end for the project . If you already know how to cascade style sheets (CSS) Add to based on React In the project , You can skip this tutorial .
I won't go into too much detail here
Make calls between containers
For developers ,Internet One of the most important functions of a computer is the ability to build programs from another container 、 Deploy and invoke shared functions in a container . This function of calling between containers ( Sometimes it's also called Call between containers ) send You can reuse and share functionality across multiple applications .
for example , You may want to create one for a professional network 、 An application for organizing community events or fund-raising activities . Each of these applications may have a social component , Enables users to follow certain standards or common interests ( For example, friends and family members or current and former colleagues ) Identify social relationships .
To solve this social component , You might want to create a container for storing user relationships , Then write your professional network 、 A community organization or fundraising application to import and invoke functions defined in the container for social relationships . then , You can build other applications to use the social contact container or extend the functionality provided by the social contact container , Make it useful to the wider community of other developers .
be based on Motoko Of LinkedUp The sample application provides a simple implementation of an open professional network , Demonstrates how to use inter container calls in a project .
LinkedUp The sample application is implemented using the following container :
- The
linkedupContainers are created and stored as basic profiles for users , Including work experience and educational background . - The
connectdThe container creates and stores user connections . - The
linkedup_assetsContainer storage front-end assets , Include JavaScript Of ,HTML and CSS file , Define user interface
Before you start
Before building the sample application , Please verify the following :
- You have downloaded and installed DFINITY Canister SDK package
- You have stopped any... Running on the local computer Internet Computer network processes .
Download Demo
To use LinkedUp The sample application tests inter container calls :
Open the terminal housing and switch to the one you use for Internet Folder for computer sample projects .
clone
linkedupThe repository .git clone https://github.com/dfinity/linkedup.gitChange to
linkedupThe local working directory of the repository .cd linkedupInstall the node module by running the following command :
npm installIf necessary, , Please fix any vulnerabilities found by running the following command :
npm audit fixdfx.jsonOpen the file in a text editor and verifydfxSet up withdfxThe executable you installed has the same version number .
Start the local network
In the build linkedup Before the project , You need to connect to Internet computer network , Or run it locally in your development environment , Or run remotely on a subnet that you can access .
Start the network locally :
Open a new terminal window or tab on the local computer .
If necessary, , Navigate to the root directory of the project .
Start on the local computer by running the following command Internet computer network :
dfx start --background Copy
In the local Internet After the computer network completes its startup operation , You can go on to the next step .
Register container identifier
Before you connect to a that runs locally in your development environment Internet After the computer network , You can register with the network to generate a unique container identifier for your project .
To register the container identifier for the local network :
if necessary , Please check if you are still in the project directory .
Register a unique container identifier for the project by running the following command :
dfx canister create --allThe command shows
dfx.jsonNetwork specific container identifier of the container defined in the configuration file ."connectd" canister created with canister id: "75hes-oqbaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q" "linkedup" canister created with canister id: "cxeji-wacaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q" "linkedup_assets" canister created with canister id: "7kncf-oidaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q"please remember , Because you are running locally Internet Computer , Therefore, these identifiers are only valid on the local network . To deploy a container on a remote network , You must use
--networkCommand line options and a specific network name or address to connect to the network , To register the identifier on this network .
Build and deploy demonstration projects
To build and deploy LinkUp Sample application , Please perform the following steps :
pwdIf necessary, , Please check whether you are still in the project directory by running the command .Build... By running the following command LinkedUp Containers :
dfx buildDeploy the project on the local network by running the following command :
dfx canister install --allYou should see the container identifier for the and container
connectd,linkedupandlinkedup_assetsA message with something similar to :Installing code for canister connectd, with canister_id 75hes-oqbaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q Installing code for canister linkedup, with canister_id cxeji-wacaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q Installing code for canister linkedup_assets, with canister_id 7kncf-oidaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-qCopy command
linkedup_assetsReturned container identifierdfx canister install.In this sample application , Only
linkedup_assetsContainers contain front-end assets for accessing application functionality . therefore , To open an application in a browser , You need to specifylinkedup_assetsContainer Identifier .linkedup_assetsstay Web Open container in browser .for example , If bound to the default localhost Address and port number , be URL It looks like :
http://127.0.0.1:8000/?canisterId=7kncf-oidaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q
Create profiles and connections
To run LinkedUp Demonstration of the sample application , Please perform the following steps :
Open a browser tab or window .
type Web Server hostname 、 Port and
canisterIdkeyword , And thenlinkedup_assetsThe container identifier is pasted to be displayed URL.127.0.0.1:8000/?canisterId=<ic-identifier-for-linkedup-assets>The browser displays an introduction page .
A public-private key pair will be automatically generated to establish your identity to access the container , Therefore, you do not need to provide a user name and password or register an account to store your identity before using the service .
Click on Sign in .
The browser displays an empty profile page .

Click on edit , Enter your profile information , Copy and paste the picture address of the avatar photo , And then click Submit .

single click Submit after , You will have a profile that contains some work history you can view .
for example :

Add another profile
here , There are no other profiles to search for or add as connections . To try out search and connect , You can :
- Run a script , Populate the sample application with some additional configuration files .
- Manually create a profile by opening a private window .
For this tutorial , You will manually create another configuration file .
To add a user profile with different identities :
In the upper right corner of the browser window , Click the appropriate icon to display the browser's menu options .
for example , If you are using Google Chrome, Click the vertical ellipse to display “ more ” menu .
If you are using Google Chrome, Please click on the “** New stealth window ”, If you are using Firefox, Please click on the “**** New privacy window ”,** So you can navigate to the container , Instead of generating user identities in the initial browser connection to the container .
In the first browser session URL Copy and paste into the private browsing window , And then click Sign in .

Please note that , There is no profile in the private browsing window , But your original configuration file is still visible in the initial browser tab .
Click on edit , Enter your profile information , Copy and paste the picture address of the avatar photo , And then click Submit .

single click Submit after , You will get a second profile , It contains some work history that you can view .
for example :

- Type the first or last name in the first profile you created ( for example , If you are Maya Garcia Created configuration file , Please type the Maya), And then click “ Search for ”.

The profiles that match your search criteria will be displayed .

- Select a contact from the search results , Wait for the connection button to appear , And then click Connect .

When the connection request is completed , The second profile shows the connection to the first profile . for example :

Use your original configuration file to return to the browser tab .
If you want to create a connection between the original profile and the profile you created in the private browsing window , You can search by repeating 、 Select and connect steps to achieve .
Explore profiles
Now that you know the basic functionality of the sample application , You can learn how to use some context of configuration settings and source files .
To browse the configuration file :
- Switch to
linkedupCatalog , Then open the project'sdfx.jsonfile . - Please note that , Two main containers are defined ,
connectdalsolinkedupEach container has amain.moSource file . - Please note that ,
linkedup_assetsContainersmain.jsWith CSS and HTML The form of the file specifies the front entry point of the asset . - Please note that , The application uses the default server IP Address and port number .
Explore the connected source code
Social relations container Source code connectd Organized into the following documents :
- The
digraph.moThe file provides the function of creating directed graphs of vertices and edges to describe user connections . - stay
main.moContains used to define and be able to be defined by LinkedUp The example application is called the connected actor and key function associated with the user profile . - The
types.moThe file defines a vertex mapping to the user identity when using custom typesdigraphandmainProgram files .
Explore the source code of the link
The source code of the professional profile with work experience and educational background is organized into the following files :
- The
main.moFile contains LinkedUp The roles and key functions of the sample application . - The
types.moThe file defines custom types , These custom types describemainstaylinkedupUser identity and profile fields imported and used in the container's program file . - The
utils.moFile provides help functions .
Query and update operations
In the use of LinkedUp Sample application , You may notice some actions ( For example, viewing a configuration file or performing a search ) Returns results almost immediately . Other operating ( For example, create a profile or add a connection ) It takes longer .
These performance differences indicate that in linkedup The difference between using query and update calls in the container .
for example , stay src/linkedup/main.mo In file ,create and update The function is an update call that changes the state of a container , But the program uses get and search Function to view or search the configuration file :
// Profiles
public shared(msg) func create(profile: NewProfile): async () {
directory.createOne(msg.caller, profile);
};
public shared(msg) func update(profile: Profile): async () {
if(Utils.hasAccess(msg.caller, profile)) {
directory.updateOne(profile.id, profile);
};
};
public query func get(userId: UserId): async Profile {
Utils.getProfile(directory, userId)
};
public query func search(term: Text): async [Profile] {
directory.findBy(term)
};
Interaction between containers
In this sample application ,linkedup The container makes use of the functions defined in the container connectd. This separation simplifies the code in each container , It also shows how to extend a project by calling a generic function defined in a container from one or more other containers .
To make public functions defined in one container available in another container :
importAdd a statement to the call container .In this example , Common functions are in
connectdContainer defined bylinkedupContainer call .therefore ,
src/linkedup/main.moInclude the following code :// Make the Connectd app's public methods available locally import Connectd "canister:connectd";running
Use
canister.functionSyntax calls public methods in the imported container .In this example ,
linkedupThe container calls... In the import containerconnectandgetConnectionsfunctionconnectd.
You can see enable... In the source file linkedup Container and connectd Interactive between containers main.mo Code .
for example ,src/connectd/main.mo The following functions are defined :
actor Connectd {
flexible var graph: Digraph.Digraph = Digraph.Digraph();
public func healthcheck(): async Bool { true };
public func connect(userA: Vertex, userB: Vertex): async () {
graph.addEdge(userA, userB);
};
public func getConnections(user: Vertex): async [Vertex] {
graph.getAdjacent(user)
};
};
Because of the Import sentence , these connectd Function can be used for linkedup Containers , also src/linkedup/main.mo Contains the following code :
// Connections
public shared(msg) func connect(userId: UserId): async () {
// Call Connectd's public methods without an API
await Connectd.connect(msg.caller, userId);
};
public func getConnections(userId: UserId): async [Profile] {
let userIds = await Connectd.getConnections(userId);
directory.findMany(userIds)
};
public shared(msg) func isConnected(userId: UserId): async Bool {
let userIds = await Connectd.getConnections(msg.caller);
Utils.includes(userId, userIds)
};
// User Auth
public shared query(msg) func getOwnId(): async UserId { msg.caller }
};
Stop the local network
After you have finished your linkedup After the test of the procedure , You can stop local Internet computer network , So that it will not continue to run in the background .
To stop the local network :
In the terminal that displays the network operation , Press Control-C Interruptible local network processes .
Stop... By running the following command Internet computer network :
dfx stop
Add access control with identity
Applications often need role-based permissions to control what different users can do .
To illustrate how to create and switch user identities , This tutorial creates a simple program , Display different greetings for users assigned to different roles .
In this case , There are three named roles owner—— admin、 and authorized.
- Allocated
adminUsers of the role will see the display Greetings fromYou have a role with administrative privileges. - Allocated
authorizedUsers of the role will see the display Greetings fromWould you like to play a game?. - Users who are not assigned one of these roles will see the display Greetings from
Nice to meet you!.
Besides , Only the user identity that initializes the container is assigned owner role , Only owner and admin Role can be assigned to other users .
In a nutshell , Each user has a public key / Private key pair . The public key is combined with the container identifier accessed by the user to form a security principal , Can then be used as a message caller to verify that the Internet The function call of the container on the computer . The following figure provides a simplified view of how user authentication authenticates the message caller .

Before you start
Before you start this tutorial , Please verify the following :
- You have downloaded and installed DFINITY Canister SDK package
- You have run at least one command to
defaultCreate your user identity . about$HOME/.config/dfx/identity/All the items in the catalog , Your default user identity will be stored globally . - If you use Visual Studio Code As IDE, You have made a reservation for Motoko Installed Visual Studio Code plug-in unit .
- You have stopped any... Running on the local computer Internet Computer network processes .
Create a new project
Create a new project directory for testing access control and switching user identities :
If you haven't opened , Please open a terminal shell on the local computer .
If you are using Internet Computer project , Please switch to the one you use for Internet Folder for computer projects .
Create a new project by running the following command :
dfx new access_helloSwitch to your project directory by running the following command :
cd access_hello
Modify the default program
In this tutorial , You will replace the template source file with a program that has the ability to assign and retrieve roles .
Modify the default program :
src/access_hello/main.moOpen the file in a text editor and delete the existing contents .Copy and paste the following sample code into a file :
// Import base modules import AssocList "mo:base/AssocList"; import Error "mo:base/Error"; import List "mo:base/List"; shared({ caller = initializer }) actor class() { // Establish role-based greetings to display public shared({ caller }) func greet(name : Text) : async Text { if (has_permission(caller, #assign_role)) { return "Hello, " # name # ". You have a role with administrative privileges." } else if (has_permission(caller, #lowest)) { return "Welcome, " # name # ". You have an authorized account. Would you like to play a game?"; } else { return "Greetings, " # name # ". Nice to meet you!"; } }; // Define custom types public type Role = { #owner; #admin; #authorized; }; public type Permission = { #assign_role; #lowest; }; private stable var roles: AssocList.AssocList<Principal, Role> = List.nil(); private stable var role_requests: AssocList.AssocList<Principal, Role> = List.nil(); func principal_eq(a: Principal, b: Principal): Bool { return a == b; }; func get_role(pal: Principal) : ?Role { if (pal == initializer) { ?#owner; } else { AssocList.find<Principal, Role>(roles, pal, principal_eq); } }; // Determine if a principal has a role with permissions func has_permission(pal: Principal, perm : Permission) : Bool { let role = get_role(pal); switch (role, perm) { case (?#owner or ?#admin, _) true; case (?#authorized, #lowest) true; case (_, _) false; } }; // Reject unauthorized user identities func require_permission(pal: Principal, perm: Permission) : async () { if ( has_permission(pal, perm) == false ) { throw Error.reject( "unauthorized" ); } }; // Assign a new role to a principal public shared({ caller }) func assign_role( assignee: Principal, new_role: ?Role ) : async () { await require_permission( caller, #assign_role ); switch new_role { case (?#owner) { throw Error.reject( "Cannot assign anyone to be the owner" ); }; case (_) {}; }; if (assignee == initializer) { throw Error.reject( "Cannot assign a role to the canister owner" ); }; roles := AssocList.replace<Principal, Role>(roles, assignee, principal_eq, new_role).0; role_requests := AssocList.replace<Principal, Role>(role_requests, assignee, principal_eq, null).0; }; public shared({ caller }) func request_role( role: Role ) : async Principal { role_requests := AssocList.replace<Principal, Role>(role_requests, caller, principal_eq, ?role).0; return caller; }; // Return the principal of the message caller/user identity public shared({ caller }) func callerPrincipal() : async Principal { return caller; }; // Return the role of the message caller/user identity public shared({ caller }) func my_role() : async ?Role { return get_role(caller); }; public shared({ caller }) func my_role_request() : async ?Role { AssocList.find<Principal, Role>(role_requests, caller, principal_eq); }; public shared({ caller }) func get_role_requests() : async List.List<(Principal,Role)> { await require_permission( caller, #assign_role ); return role_requests; }; public shared({ caller }) func get_roles() : async List.List<(Principal,Role)> { await require_permission( caller, #assign_role ); return roles; }; };Let's look at some of the key elements of this program :
You may notice that
greetThe function isgreetVariations of the functions you saw in the previous tutorial .however , In this program , The
greetThe function uses the message caller to determine which permissions should be applied , And according to the permissions associated with the caller , Determine the greeting to display .The program defines two custom types —— One is for
Roles, One is forPermissions.The
assign_rolesThe function enables the message caller to assign roles to the principal associated with the identity .The
callerPrincipalFunction enables you to return the principal associated with the identity .The
my_roleFunction enables you to return the role associated with the identity .
Save your changes and close
main.moFile to continue .
Start the local network
In the build access_hello Before the project , You need to connect to Internet computer network , Or run it locally in your development environment , Or run remotely on a subnet that you can access .
Start the network locally :
Open a new terminal window or tab on the local computer .
If necessary, , Navigate to the root directory of the project .
Start on the local computer by running the following command Internet computer network :
dfx start --backgroundIn the local Internet After the computer network completes its startup operation , You can go on to the next step .
register 、 Build and deploy applications
Before you connect to a that runs locally in your development environment Internet After the computer network , You can run this dfx deploy Command one-step registration 、 Build and deploy your application . You can also use each step performed separately
if necessary , Please check that you are still in the root directory of the project .
access_helloRegister by running the following command 、 Build and deploy backend applications :dfx deploy access_helloCreating a wallet canister on the local network. The wallet canister on the "local" network for user "default" is "rwlgt-iiaaa-aaaaa-aaaaa-cai" Deploying: access_hello Creating canisters... Creating canister "access_hello"... "access_hello" canister created with canister id: "rrkah-fqaaa-aaaaa-aaaaq-cai" Building canisters... Installing canisters... Installing code for canister access_hello, with canister_id rrkah-fqaaa-aaaaa-aaaaq-cai Deployed canisters.
Check the current identity context
Before we create any other identities , Let's check out your default The primary identifier associated with your identity and the periodic wallet of your identity default. stay Internet On computer , The subject is the user 、 Containers 、 Internal representation of a node or subnet . The textual representation of the principal is the external identifier that you see when using the principal data type .
View your current identity and policies :
Verify the identity of the current activity by running the following command :
dfx identity whoamiThis command displays output similar to the following :
defaultdefaultCheck the principal of the user's identity by running the following command :dfx identity get-principalThis command displays output similar to the following :
zen7w-sjxmx-jcslx-ey4hf-rfxdq-l4soz-7ie3o-hti3o-nyoma-nrkwa-cqedefaultCheck the roles associated with the user identity by running the following command :dfx canister --wallet=$(dfx identity get-wallet) call access_hello my_roleThis command displays output similar to the following :
(opt variant { owner })
Create a new user identity
To start testing access control in our program , Let's create some new user identities and assign these users to different roles .
To create a new user identity :
if necessary , Please check if you are still in the project directory .
Create a new administrative user identity by running the following command :
dfx identity new ic_adminThis command displays output similar to the following :
Creating identity: "ic_admin". Created identity: "ic_admin".Call the
my_roleFunction to see that your new user identity has not been assigned to any roles .dfx --identity ic_admin canister call access_hello my_roleThis command displays output similar to the following :
Creating a wallet canister on the local network. The wallet canister on the "local" network for user "ic_admin" is "ryjl3-tyaaa-aaaaa-aaaba-cai" (null)By running the following command , Switch the currently active identity context to use the new
ic_adminUser identity and display withic_adminThe principal associated with the user :dfx identity use ic_admin && dfx identity get-principalThis command displays output similar to the following :
Using identity: "ic_admin". c5wa6-3irl7-tuxuo-4vtyw-xsnhw-rv2a6-vcmdz-bzkca-vejmd-327zo-waeaccess_helloCheck the body used to invoke the container by running the following command :dfx canister call access_hello callerPrincipalThis command displays output similar to the following :
(principal "ryjl3-tyaaa-aaaaa-aaaba-cai")By default ,cycles The wallet identifier is used to call
access_helloThe body of the method in the container . However , To illustrate access control , We want to use the principal associated with the user context , Not the cycle wallet . however , Before we get to this point , Let's makeic_adminThe user assigns a role . So , We need to switch todefaultHave the right toownerUser identity of the role .
Assign roles to identities
Assign the administrator role to ic_admin identity :
defaultBy running the following command , Switch the currently active identity context to use user identity :dfx identity use defaultBy using Candid The syntax runs a command similar to the following , by
ic_adminSubject assignmentadminrole :dfx canister --wallet=$(dfx identity get-wallet) call access_hello assign_role '((principal "c5wa6-3irl7-tuxuo-4vtyw-xsnhw-rv2a6-vcmdz-bzkca-vejmd-327zo-wae"),opt variant{admin})'
+ perhaps , You can rerun the command to invoke my_role Function to verify the role assignment .
dfx --identity ic_admin canister call access_hello my_role
+ This command displays output similar to the following :
(opt variant { admin })
By running the following command , Use the role you just assigned
greetOfic_adminCall this function as the useradmin:dfx --identity ic_admin canister call access_hello greet "Internet Computer Admin"This command displays output similar to the following :
( "Hello, Internet Computer Admin. You have a role with administrative privileges.", )
Add authorized user identity
here , You have a default with owner Character's ic_admin User identity and a user identity with roles admin. Let's add another user identity and assign it to authorized role . however , For this example , We will use environment variables to store the user's principal .
Add a new authorized user identity :
if necessary , Please check if you are still in the project directory .
Create a new authorized user identity by running the following command :
dfx identity new alice_authThis command displays output similar to the following :
Creating identity: "alice_auth". Created identity: "alice_auth".alice_authBy running the following command , Switch the currently active identity context to use the new user identity :dfx identity use alice_authalice_authStore the user's principal in the environment variable by running the following command :ALICE_ID=$(dfx identity get-principal)You can verify the stored principal by running the following command :
echo $ALICE_IDThis command displays output similar to the following :
b5quc-npdph-l6qp4-kur4u-oxljq-7uddl-vfdo6-x2uo5-6y4a6-4pt6v-7qeBy running the following command , Use
ic_adminIdentity willauthorizedRole assignmentalice_auth:dfx --identity ic_admin canister call access_hello assign_role "(principal \"$ALICE_ID\", opt variant{authorized})"Call the
my_roleFunction to verify the role assignment .dfx --identity alice_auth canister call access_hello my_roleThis command displays output similar to the following :
(opt variant { authorized })By running the following command , Use the role you just assigned
greetOfalice_authCall this function as the userauthorized:dfx canister call access_hello greet "Alice"This command displays output similar to the following :
( "Welcome, Alice. You have an authorized account. Would you like to play a game?", )
Add unauthorized user identity
You have now seen a simple example of creating users with specific roles and permissions . The next step is to create user identities that are not assigned to roles or granted any special permissions .
Add unauthorized user identity :
if necessary , Please check if you are still in the project directory .
if necessary , Check your current active identity by running the following command :
dfx identity whoamiCreate a new user identity by running the following command :
dfx identity new bob_standardThis command displays output similar to the following :
Creating identity: "bob_standard". Created identity: "bob_standard".bob_standardStore the user's principal in the environment variable by running the following command :BOB_ID=$(dfx --identity bob_standard identity get-principal)Try to use
bob_standardIdentity assignment roles .dfx --identity bob_standard canister call access_hello assign_role "(principal \"$BOB_ID\", opt variant{authorized})"This command returns
unauthorizederror .Try to use
defaultUser identitybob_standardOfownerTo run the following command :dfx --identity default canister --wallet=$(dfx --identity default identity get-wallet) call access_hello assign_role "(principal \"$BOB_ID\", opt variant{owner})"This command failed , Because the user cannot be assigned
ownerrole .By running the following command ,
greetUsebob_standardCall this function as the user :dfx --identity bob_standard canister --no-wallet call access_hello greet "Bob"This command displays output similar to the following :
("Greetings, Bob. Nice to meet you!")
Set user identity for multiple commands
up to now , You have learned how to create and switch user identities for a single command . You can also specify the user identity to use , Then run multiple commands in the context of that user identity .
To run multiple commands as a user :
if necessary , Please check if you are still in the project directory .
List the currently available user identities by running the following command :
dfx identity listThis command displays output similar to the following , With an asterisk indicating the identity of the currently active user .
alice_auth bob_standard default * ic_adminIn this example ,
defaultUnless you explicitly choose a different identity , Otherwise, the user identity will be used .Select a new user identity from the list , And make it an active user context by running a command similar to the following :
dfx identity use ic_admin+ This command displays output similar to the following :
Using identity: "ic_admin".If you re run the
dfx identity listcommand ,ic_adminThe user ID will display an asterisk , To indicate that it is the currently active user context .You can now run the command as the selected user , No need
--identitySpecify... On the command line .
Stop the local network
After you have finished experimenting with the program and using the identity , You can stop local Internet computer network , So that it will not continue to run in the background .
To stop the local network :
In the terminal that displays the network operation , Press Control-C Interruptible local network processes .
Stop... By running the following command Internet computer network :
dfx stop
Accept the cycle from the wallet
When doing local development , You can use the default wallet sending cycle in the project , View your cycle balance . But what about programs that need to receive and destroy these cycles to perform their functions and provide services to users ? This tutorial provides a simple example of how to add functions that receive cycles and check cycle balances to the default template program .
This example contains the following :
- The
wallet_balanceThe function enables you to check the current loop balance of the container . - The
wallet_receiveFunction enables a program to accept a loop sent to a container . - The
greetThe function takes a text argument and displays a greeting in the terminal . - The
ownerFunction returns the body used by the message caller .
Before you start
Before you start this tutorial , Please verify the following :
- You have downloaded and installed DFINITY Canister SDK package
- If you use Visual Studio Code As IDE, You have made a reservation for Motoko Installed Visual Studio Code plug-in unit .
- You have stopped any... Running on the local computer Internet Computer network processes .
Create a new project
Create a new project directory for testing access control and switching user identities :
If you haven't opened , Please open a terminal shell on the local computer .
If you are using Internet Computer project , Please switch to the one you use for Internet Folder for computer projects .
Create a new project by running the following command :
dfx new cycles_helloSwitch to your project directory by running the following command :
cd cycles_hello
Modify the default program
For this tutorial , You will modify the template source code to include new functions for accepting cycles and checking cycle balance .
Modify the default program :
src/cycles_hello/main.moOpen the file in a text editor and delete the existing contents .Copy and paste the following sample code into a file :
import Nat64 "mo:base/Nat64"; import Cycles "mo:base/ExperimentalCycles"; shared(msg) actor class HelloCycles ( capacity: Nat ) { var balance = 0; // Return the current cycle balance public shared(msg) func wallet_balance() : async Nat { return balance; }; // Return the cycles received up to the capacity allowed public func wallet_receive() : async { accepted: Nat64 } { let amount = Cycles.available(); let limit : Nat = capacity - balance; let accepted = if (amount <= limit) amount else limit; let deposit = Cycles.accept(accepted); assert (deposit == accepted); balance += accepted; { accepted = Nat64.fromNat(accepted) }; }; // Return the greeting public func greet(name : Text) : async Text { return "Hello, " # name # "!"; }; // Return the principal of the caller/user identity public shared(msg) func owner() : async Principal { let currentOwner = msg.caller; return currentOwner; }; };Let's look at some of the key elements of this program :
- The program imports a Motoko Base library
ExperimentalCycles—— It provides the basic function of using loops . - The program uses a
actor classRather than a single actor, So it can have multiple actor Instance to acceptcapacityDifferent loop quantities for all instances , At most a . - take
capacityPass as parameter to actor class . - stay
msg.callerIdentify the principal associated with the call .
- The program imports a Motoko Base library
Save your changes and close
main.moFile to continue .
Start the local network
In the build access_hello Before the project , You need to connect to Internet computer network , Or run it locally in your development environment , Or run remotely on a subnet that you can access .
Start the network locally :
Open a new terminal window or tab on the local computer .
If necessary, , Navigate to the root directory of the project .
Start on the local computer by running the following command Internet computer network :
dfx start --clean --backgroundIn the local Internet After the computer network completes its startup operation , You can go on to the next step .
register 、 Build and deploy applications
Before you connect to a that runs locally in your development environment Internet After the computer network , You can register locally 、 Build and deploy your application .
Deploy the application locally :
if necessary , Please check that you are still in the root directory of the project .
Register by running the following command 、 Build and deploy your application :
dfx deploy --argument '(360000000000)'This example will
capacityContainer of Set to 360,000,000,000 Secondary cycle . Ofdfx deployThe command output then displays the relevant operations it performs , Include the identity information associated with the wallet container created by this local item and the wallet container identifier .for example :
Deploying all canisters. Creating canisters... Creating canister "cycles_hello"... Creating the canister using the wallet canister... Creating a wallet canister on the local network. The wallet canister on the "local" network for user "default" is "rwlgt-iiaaa-aaaaa-aaaaa-cai" "cycles_hello" canister created with canister id: "rrkah-fqaaa-aaaaa-aaaaq-cai" Creating canister "cycles_hello_assets"... Creating the canister using the wallet canister... "cycles_hello_assets" canister created with canister id: "ryjl3-tyaaa-aaaaa-aaaba-cai" Building canisters... Building frontend... Installing canisters... Installing code for canister cycles_hello, with canister_id rrkah-fqaaa-aaaaa-aaaaq-cai Installing code for canister cycles_hello_assets, with canister_id ryjl3-tyaaa-aaaaa-aaaba-cai Authorizing our identity (default) to the asset canister... Uploading assets to asset canister... Deployed canisters.
Test the application
In the local Internet After the application is deployed on the computer network , You can experiment with the wallet function and use dfx canister call Command to test your program .
To test the application :
defaultCheck the principal of the user's identity by running the following command :dfx canister call cycles_hello ownerThis command displays output similar to the following for the current identity :
(principal "g3jww-sbmtm-gxsag-4mecu-72yc4-kef5v-euixq-og2kd-sav2v-p2sb3-pae")If you have not changed the to run this
dfx deployThe identity of the command , By running thedfx identity get-principalCommand gets the same body . It's important , Because you must be the owner of the wallet container to perform certain tasks , For example, send cycle or grant other Custodian Permission of identity sending cycle .Check the initial wallet cycle balance by running the following command :
dfx canister call cycles_hello wallet_balanceYou have not sent any loops to the container , Therefore, the command displays the following balance :
(0)cycles_helloBy running a command similar to the following , Use the container body to send some cycles from your default wallet container to the container :dfx canister call rwlgt-iiaaa-aaaaa-aaaaa-cai wallet_send '(record { canister = principal "rrkah-fqaaa-aaaaa-aaaaq-cai"; amount = (256000000000:nat64); } )'If the quantity you specify is less than the allowed capacity , Or the amount you specify when you run the command , Call this
wallet_balanceFunction to seecycles_helloThe container has the number of cycles you transfer .capacity``dfx deploydfx canister call cycles_hello wallet_balanceThis command displays output similar to the following :
(256_000_000_000)wallet_balanceCall this function by running a command similar to the following to see the number of cycles in the default wallet :dfx canister call rwlgt-iiaaa-aaaaa-aaaaa-cai wallet_balanceThe command uses Candid The format returns the balance of the wallet container identifier you specify as the record . for example , The command may display a containing a
amountField ( from hash Express3_573_748_184) and 97,738,624,621,042 A record of the balance of periods , As shown below :(record { 3_573_748_184 = 97_738_624_621_042 })For this simple tutorial , The period is consumed only from the balance in the default wallet container , Not from
cycles_helloConsumed in the container .greetCall this function by running a command similar to the following :dfx canister call cycles_hello greet '("from DFINITY")'Call the... Again
wallet_balanceFunction to view the number of cycles deducted from your default wallet :dfx canister call rwlgt-iiaaa-aaaaa-aaaaa-cai wallet_balancefor example , You might get a similar result :
( Record { 3_573_748_184 = 97_638_622_179_500 })
Stop the local network
After you have tested the program , You can stop local Internet computer network , So that it will not continue to run in the background .
To stop the local network :
In the terminal that displays the network operation , Press Control-C Interruptible local network processes .
Stop... By running the following command Internet computer network :
dfx stop
eturn currentOwner;
};
};
Let's look at some of the key elements of this program :
- The program imports a Motoko Base library `ExperimentalCycles`—— It provides the basic function of using loops .
- The program uses a `actor class` Rather than a single actor, So it can have multiple actor Instance to accept `capacity` Different loop quantities for all instances , At most a .
- take `capacity` Pass as parameter to actor class .
- stay `msg.caller` Identify the principal associated with the call .
3. Save your changes and close `main.mo` File to continue .
### Start the local network
In the build `access_hello` Before the project , You need to connect to Internet computer network , Or run it locally in your development environment , Or run remotely on a subnet that you can access .
Start the network locally :
1. Open a new terminal window or tab on the local computer .
2. If necessary, , Navigate to the root directory of the project .
3. Start on the local computer by running the following command Internet computer network :
```bash
dfx start --clean --background
In the local Internet After the computer network completes its startup operation , You can go on to the next step .
register 、 Build and deploy applications
Before you connect to a that runs locally in your development environment Internet After the computer network , You can register locally 、 Build and deploy your application .
Deploy the application locally :
if necessary , Please check that you are still in the root directory of the project .
Register by running the following command 、 Build and deploy your application :
dfx deploy --argument '(360000000000)'This example will
capacityContainer of Set to 360,000,000,000 Secondary cycle . Ofdfx deployThe command output then displays the relevant operations it performs , Include the identity information associated with the wallet container created by this local item and the wallet container identifier .for example :
Deploying all canisters. Creating canisters... Creating canister "cycles_hello"... Creating the canister using the wallet canister... Creating a wallet canister on the local network. The wallet canister on the "local" network for user "default" is "rwlgt-iiaaa-aaaaa-aaaaa-cai" "cycles_hello" canister created with canister id: "rrkah-fqaaa-aaaaa-aaaaq-cai" Creating canister "cycles_hello_assets"... Creating the canister using the wallet canister... "cycles_hello_assets" canister created with canister id: "ryjl3-tyaaa-aaaaa-aaaba-cai" Building canisters... Building frontend... Installing canisters... Installing code for canister cycles_hello, with canister_id rrkah-fqaaa-aaaaa-aaaaq-cai Installing code for canister cycles_hello_assets, with canister_id ryjl3-tyaaa-aaaaa-aaaba-cai Authorizing our identity (default) to the asset canister... Uploading assets to asset canister... Deployed canisters.
Test the application
In the local Internet After the application is deployed on the computer network , You can experiment with the wallet function and use dfx canister call Command to test your program .
To test the application :
defaultCheck the principal of the user's identity by running the following command :dfx canister call cycles_hello ownerThis command displays output similar to the following for the current identity :
(principal "g3jww-sbmtm-gxsag-4mecu-72yc4-kef5v-euixq-og2kd-sav2v-p2sb3-pae")If you have not changed the to run this
dfx deployThe identity of the command , By running thedfx identity get-principalCommand gets the same body . It's important , Because you must be the owner of the wallet container to perform certain tasks , For example, send cycle or grant other Custodian Permission of identity sending cycle .Check the initial wallet cycle balance by running the following command :
dfx canister call cycles_hello wallet_balanceYou have not sent any loops to the container , Therefore, the command displays the following balance :
(0)cycles_helloBy running a command similar to the following , Use the container body to send some cycles from your default wallet container to the container :dfx canister call rwlgt-iiaaa-aaaaa-aaaaa-cai wallet_send '(record { canister = principal "rrkah-fqaaa-aaaaa-aaaaq-cai"; amount = (256000000000:nat64); } )'If the quantity you specify is less than the allowed capacity , Or the amount you specify when you run the command , Call this
wallet_balanceFunction to seecycles_helloThe container has the number of cycles you transfer .capacity``dfx deploydfx canister call cycles_hello wallet_balanceThis command displays output similar to the following :
(256_000_000_000)wallet_balanceCall this function by running a command similar to the following to see the number of cycles in the default wallet :dfx canister call rwlgt-iiaaa-aaaaa-aaaaa-cai wallet_balanceThe command uses Candid The format returns the balance of the wallet container identifier you specify as the record . for example , The command may display a containing a
amountField ( from hash Express3_573_748_184) and 97,738,624,621,042 A record of the balance of periods , As shown below :(record { 3_573_748_184 = 97_738_624_621_042 })For this simple tutorial , The period is consumed only from the balance in the default wallet container , Not from
cycles_helloConsumed in the container .greetCall this function by running a command similar to the following :dfx canister call cycles_hello greet '("from DFINITY")'Call the... Again
wallet_balanceFunction to view the number of cycles deducted from your default wallet :dfx canister call rwlgt-iiaaa-aaaaa-aaaaa-cai wallet_balancefor example , You might get a similar result :
( Record { 3_573_748_184 = 97_638_622_179_500 })
Stop the local network
After you have tested the program , You can stop local Internet computer network , So that it will not continue to run in the background .
To stop the local network :
In the terminal that displays the network operation , Press Control-C Interruptible local network processes .
Stop... By running the following command Internet computer network :
dfx stop
边栏推荐
- 安装CUDA+CUSP环境,并创建第一个HelloWord入门工程
- 22 | adventure and prediction (I): hazard is both "danger" and "opportunity"
- Index invalidation caused by inaccurate MySQL statistics
- Redis master-slave replication - underlying principle
- uniapp 小程序根据权限动态生成 tabbar
- [redis problem] record a big key problem handling
- Go 接口实现原理【高阶篇】: type _interface struct
- 24 | adventure and prediction (III): thread pool in CPU
- Simple use of logs
- JMeter common commands
猜你喜欢

Overall process analysis of account book operation in fabric0.6

2022年G3锅炉水处理操作证考试题库模拟考试平台操作

18 | establish data path (middle): instruction + operation =cpu

Operation of simulated examination platform for examination question bank of G3 boiler water treatment operation certificate in 2022

23 | adventure and prediction (II): relay race in the assembly line

ERP 基础数据 概念

EHD ether coin, the hottest dpoc mining project

Hashtable source code analysis

OpenHarmony笔记-----------(一)

实践出真知--你的字节对齐和堆栈认知可能是错误的
随机推荐
ERP基础数据 金蝶
Amino encoding protocol
[MySQL] the most complete MySQL monitoring project
Differences between Merkle DAG and Merkle tree
Install cuda+cusp environment and create the first helloword starter project
The uniapp applet dynamically generates tabbar based on permissions
5. fabric2.2 installation and submission contract (using official demo)
Index push down (ICP) for mysql5.6
Overall process analysis of account book operation in fabric0.6
A troubleshooting process for database timeout caused by SQL misguided
Advanced MySQL: how to learn MySQL source code
Redis master-slave replication - the underlying principle of partial resynchronization
ERP 基础数据 概念
分布式系统之道:Lamport 逻辑时钟
Examination question bank and simulation examination for special operation certificate of safety management personnel of hazardous chemical business units in 2022
SFTP login and download file script
IDS persistence ---rdb
基于paddlepaddle的新冠肺炎识别
22 | 冒险和预测(一):hazard是“危”也是“机”
Win10系统如何修改桌面路径