作者:Lyric 编辑:比特汪 本文已通过PRESSone合约购买个人授权许可(非排他性),可以点击阅读原文查看。
我是 @lyric,本教程应 Mixin COO @薄荷 邀约而写,旨在向区块链领域以外的工程师们介绍如何以依托 Mixin Network,用最简单的方式开发自己的区块链应用程序。
本文是系列教程的第一篇,如果对本文感兴趣,你可以:
订阅我的博客 lyric.im
订阅我的 PRESS.one 专栏
关注我的公众号,搜索iamlyricw
或在文末给赞赏一些数字货币
方便获取后续更新。
为什么是 Mixin
从 BTC 到 ETH 到 EOS,相信很多工程师都对区块链有一些了解,并对其中的故事有所耳闻。就技术本身,无论是 BitCoin 的基础技术模型,还是从 ETH 开始智能合约,抑或是 EOS 独特的架构——可能让第一次接触的工程师会觉得有一些不适应,开发 Dapp 也变得困难。
实际上,每一条公链都(声称)有自己独特的应用场景,对此提出了特异性的技术。对于开发者来说,这些涉及复杂密码学的技术变成了进入门槛。而Mixin 做的事情是抹平了所有公链在“交易”这个层面上的差异,专注于“交易”本身。
在 Mixin Network 中,你可以使用最熟悉的技术栈和协议,轻易地将“数字货币”属性加入到自己的项目中,实现“零售、打赏、货币交易”等所有跟“交易”相关的功能;也可以借助 Mixin Network 的 DAG 网络,将(广义的)“区块链”属性加入到自己的项目中,实现“版权、存证、追溯、信息披露”等所有跟“区块链”相关的功能。
综上所述,使用 Mixin Network,可以让你的想法很轻松地在区块链上实现,不需要关注很多繁琐的技术细节。
小贴士
所谓 Dapp,为 Decentralized Application[^1] 的简称。一般认为 Dapp 由智能合约(即在区块链上运作的代码)编写。
Mixin 对此有不同看法。Mixin 的支持者信仰 Unix 哲学[^2]中的 “让程序只做好一件事”,Mixin 只需要做好“Transaction” 这一件事,因此 Mixin 并不支持智能合约。这也是为什么你可以使用自己熟悉的技术栈来写应用,而不仅仅局限于少数程序设计语言的原因。
注册 App
在开始之前,你需要在 Mixin Network 中注册自己的 App。在 Mixin 开发者中心https://developers.mixin.one/dashboard,提交图标、名称、描述,URL 等基本信息即可完成注册。这很类似于常见的开放服务。
注册完成后,点击 “Click here to generate...” 生产必要的密钥等信息,各部分如下图所示:
Mixin Network 把 App 当作一个用户,因此 User Id 用于在网络中唯一标识该 App。每个 App 自带一个资产账户,直接向这个 User Id 转账会进入到账户中。
而下面的其它信息,如 Client Secret、PIN、SessionId、Pin Token、Private Key 等则用来操作账户,执行更新信息、转账、查账等操作,等会儿我们会用到。请务必记住它们,并且不要泄漏。
我预先注册了一个 Hello Bot,Mixin Id 为7000101423。可以在 Mixin Messenger 中加为好友体验。
Hello world.
接下来,我们来写 Hello world。
任务描述:用户在 Mixin Messager 中向机器人说sync,机器人回复ack。
简化起见,我会在项目中使用 MixinNetwork 的 Bot SDK:github.com/MixinNetwork/bot-api-go-client,并且使用Golang 语言来进行程序设计。因此,接下来我假设你已经将 Golang 开发环境安排好了,并且知晓如何使用 Golang 编写程序。
1. 准备 SDK 和项目目录
本文的开发环境为 macOS,所用的 Golang 版本为 go1.11.2。
我们先安装 Bot SDK
$ go get -u github.com/MixinNetwork/bot-api-go-client
接下来我们可能还需要安装其它依赖的模块,请使用go get指令安装,我不再赘述。
准备一个目录,用于存放项目和源码,我将其命名为hello-bot;在其中新建config.yml,用于存放配置;最后在hello-bot下新建main.go,主要代码将在其中。
$ mkdir hello-bot
$ cd hello-bot
$ touch main.go
$ touch config.yml
2. 理解 Mixin Messenger 机器人的运作原理
在正式开始之前,先理解一下 Mixin Messenger 机器人的运作原理。
虽然 Mixin Messenger 的资产体系建立在 Mixin Network 之上,但用户和消息体系则是独立的。使用 Mixin Messenger 聊天的时候,由服务器提供消息的中转。
在服务器看来,机器人就像是一个参与聊天的普通用户。因此跟机器人聊天时,消息也会由服务器转发到机器人所在的机器,由机器人程序进行处理和应答。
由于机器人像一个普通用户,所以它也有自己的钱包(在App Dashboard上可以看到)。因此,如果涉及到转账,机器人可以通过 Mixin Network 来操作自己的账户,进行转账等自己操作。
3. 配置机器人
在上一章节"注册 App"中,我们得到了 Id 和私钥等机器人的信息,需要将它写到配置文件config.yml之中:
client_id: YOUR CLIENT ID
client_secret: YOUR CLIENT SECRET
session_id: YOUR SESSION ID
pin: YOUR PIN
pin_token: YOUR PIN TOKEN
private_key: |
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
请按照之前的信息挨个填写。其中私钥private_key是一个多行文本,请确保遵从 yaml 的多行文本语法,每一行的行首都要对齐。
在源码中,我提供了config.example.yaml,可以修改它为你的配置文件。
4. 接收消息
一个机器人,最核心的部分是消息循环。这个消息循环会不断检查服务器的消息队列,是否有给它推送新消息。
我们在main.go的main函数中,使用NewBlazeClient方法创建机器人客户端。client是一个模块级变量,方便别的函数调用:
// Create a bot client
client = bot.NewBlazeClient(
config.GetConfig().ClientID,
config.GetConfig().SessionID,
config.GetConfig().PrivateKey
)
config模块会负责从config.yml中读取必要的配置。
然后使用client.Loop开启消息循环。关键的处理函数被定义在接口handler之中,实现为OnMessage
// Start the loop
for {
if err := client.Loop(ctx, handler); err != nil {
log.Printf("Error: %v\n", err)
}
log.Println("connection loop end")
time.Sleep(time.Second)
}
type Handler struct{}
...
func (r Handler) OnMessage(ctx context.Context, msgView bot.MessageView, botID string) error {
...
}
其中,msgView是关键的参数,它包含了所有跟本次消息相关的信息。在 SDK 源码中,它的定义是这样的:
type MessageView struct {
ConversationId string // 会话 ID
UserId string // 对方用户 ID
MessageId string // 消息 ID
Category string // 消息类型,文本、图片还是视频等
Data string // 消息的数据,具体的消息内容
Status string // 消息状态
Source string
CreatedAt time.Time
UpdatedAt time.Time
}
包含了一条消息所需的全部信息。
机器人处理消息时,需要对msgView进行拆解,然后作出应答。
func (r Handler) OnMessage(ctx context.Context, msgView bot.MessageView, botID string) error {
// 我们只处理 PLAIN_TEXT 类型消息,并且只应答当前对话。
if msgView.Category == bot.MessageCategoryPlainText &&
msgView.ConversationId == bot.UniqueConversationId(config.GetConfig().ClientID, msgView.UserId) {
var data []byte
var err error
if data, err = base64.StdEncoding.DecodeString(msgView.Data); err != nil {
log.Panicf("Error: %s\n", err)
return err
}
inst := string(data)
log.Printf("I got a message from %s, it said: `%s`\n", msgView.UserId, inst)
}
...
}
首先我们确定只处理文本消息,因此要先对msgView.Category进行判断。然后使用UniqueConversationId判断消息是否来自对方所在的会话。
然后将msgView.Data进行 Base64 解码,获取到其中的消息内容,保存到变量inst之中。
5. 回复消息
接着我们来对消息进行处理。在OnMessage中,对inst的内容进行判断:
if "sync" == inst {
// Sync? Ack!
Respond(ctx, msgView, "ack")
} else {
Respond(ctx, msgView, defaultResponse)
}
如果用户发来的消息是sync,那么就让机器人回复ask;如果不是sync,则回复一句默认文字。
回复的实现在Respond函数之中,它非常简单:
func Respond(ctx context.Context, msgView bot.MessageView, msg string) {
if err := client.SendPlainText(ctx, msgView, msg); err != nil {
log.Panicf("Error: %s\n", err)
}
}
只是调用机器人客户端client.SendPlainText回复一句话给对方,回复的内容由变量msg指定。
效果如下:
这样,一个能跟你说话的机器人就完成咯。在OnMessage中添加更多逻辑,就可以让它具备更多功能,而不仅仅是回复一个单词。
小结
本章内容暂时到这里,Hello Bot 的 Mixin Id 为7000101423,可以在 Mixin Messenger 中加它为好友体验。
Hello Bot 的源码可以在https://github.com/fox-one/hello-bot获取。