文章目录
学习 Counter 的例子,并且部署到主网 https://smartcontracts.org/docs/developers-guide/tutorials/counter-tutorial.html
要求:提交主网完成部署的 Canister ID (或者链接
给 Counter 添加一个 http_request 方法,用返回 html 的方式显示当前 count 的值。
要求:
1)提交主程序源码链接
2)完成主网部署并提交链接
canister生命周期
已创建:无代码,无内存,不能接收和发送消息
正常运行:可以接收和发送消息
预备停止:允许收到发送消息的回复
停止运行:可以升级代码
余额不足维系30天时,canister会被冻结(frozen),余额为零则会被删除
canister的调用方式
Update Call更新调用:更改共识,安全性高,状态的改变是持久的,需要两步
1.改变状态
2.查询状态改变是否成功
Query Call查询调用:不更改共识,效率高,状态改变不保存
可以在函数声明的时候注明函数是什么调用
给canister发送消息请求
sender Id代表用户身份,公钥哈希值
canister Id代表智能合约身份,由系统分配
Anonymous Id匿名身份,没有签名
消息处理的步骤
用http_request方法实现网页服务
一般部署的canister可以通过candid UI,即通过官方提供的前端来显示函数
关于这部分内容很多是跟着老师视频演示模仿的,能理解大致整体,但对整体如何实现,还需要进一步学习,似乎是一个固定流程,可以直接到ic.rocks网站完成代码的复制和粘贴,就省得自己声明了。
大致的思路是定义两个对象声明,一个是HttpRequest一个是HttpResponse,输入前者,返回后者
由于这部分内容是可以公开的,所以直接贴代码
public type HeaderField = (Text, Text);
//声明一个类型,输入
public type HttpRequest = {
url : Text;
method : Text;
body : [Nat8];
headers : [HeaderField];
};
//声明一个类型,输出
public type HttpResponse = {
body : Blob;
headers : [HeaderField];
streaming_strategy : ?StreamingStrategy;
status_code : Nat16;
};
public type Key = Text;
public type ChunkId = Nat;
public type SetAssetContentArguments = {
key : Key;
sha256 : ?[Nat8];
chunk_ids : [ChunkId];
content_encoding : Text;
};
public type StreamingCallbackHttpResponse = {
token : ?StreamingCallbackToken;
body : [Nat8];
};
public type StreamingCallbackToken = {
key : Key;
sha256 : ?[Nat8];
index : Nat;
content_encoding : Text;
};
public type StreamingStrategy = {
#Callback : {
token : StreamingCallbackToken;
callback : shared query StreamingCallbackToken -> async ?StreamingCallbackHttpResponse;
};
};
//要实现的函数
…………
//调用http_request
public shared query func http_request(request:HttpRequest): async HttpResponse {
{
body = 需要返回的内容 ;
headers =[];
streaming_strategy = null;
status_code = 200;
}
}
};
由于老师的课程还在招生,所以为了防止后面的同学,直接不学抄作业,所以就把关键内容给忽略了
整体要掌握的地方是HttpResponse返回body内的内容,这个内容类型是定义成blob类型,事实证明改成text也是可以通过的。
而将输入改成blob类型,使用的是Text里面的encodeUtf8方法
在课程内容里面,老师使用Text.encodeUtf8("
Hello World
“)返回了一个helloworld作业让我们返回counter变量的值,至于要如何在motoko里面实现返回counter变量的值,自便。
本地部署后的测试结果,返回计数结果0,由于counter赋值为零了。
dfx canister call counterhomework inc "()"
通过call函数调用counterhomework里的inc函数,即计数一次,再刷新我们的canister测试页面,返回计数结果1
由此实现了,直接输入canisterid.raw.ic0.app,就能打开一个页面,因为有返回的html
ID
principal id: 通用身份标识
sender id:代表用户身份,通常是公钥的哈希值
canister id:智能合约身份,由系统分配
问题和解决
问题1:访问不到页面
显示body未验证,需要加入.raw
问题2:如何返回一个变量的值
这个难题,我是通过咨询程序员朋友和咨询大群同学解决的,具体办法是通过字符串拼接,实现返回html文本同时返回变量的值
motoko语言里面特别需要注意类型转换,例如赋值给body的最后是blob类型,而counter打印到界面的也是text字符串类型,这些都需要做类型转换,具体看文档
我起初的思路是想通过debug.Print来打印一个变量的值,但是不行,页面返回的就是debug.print,因为整体把debug.print当成字符串打印了
这里应该是有两个步骤,一是将所有内容转换成utf8后打印,用html文本的方式打开,之后是
counter变量值会被处理,进而只在html页面上显示变量的值。