导读
——
撰文|Lewis、Howe、Kahn
自 2023 年 7 月份以来,Unibot 的火爆,带起了一波 "Telegram Crypto" 的热潮,再加上 Telegram Wallet 的上线,将 TON 再次带回了大家的视线。不同于 2018 年 TON 在 Web3 行业的中文关注者比较少,本次热潮吸引来了众多中文开发者,为此 LXDAO 社区也为大家带来了一些 Telegram & TON 生态开发者入门知识,带你了解这个生态。
正文
——
文章一共 9000 字左右,一共分为 5 个部分,阅读大概需要 20 分钟。
1. Telegram 应用
1.1 Telegram Bot
2. TON 链
2.1 TON 技术特点
2.2 TON钱包
3. TON 和 Telegram 的关系
4. Telegram Bot 与 TON 集成
4.1 生态对象调用流程图
4.2 Telegram Bot 创建
4.3 Telegram Bot 开发
4.4 Example 1: Telegram Bot 集成 Wallet
4.5 TON 智能合约开发语言
4.6 TON 简单合约源码分析
4.7 Example 2: Telegram Bot 与 TON 合约集成
5. 总结
01 Telegram 应用
Telegram(非正式简称TG、电报、纸飞机)是跨平台的即时通信软件,官方提供手机版(Android、iOS、Windows Phone)、桌面版(Windows、macOS、Linux)和网页版等多种平
台客户端;同时开放应用程序接口(API),因此拥有许多第三方的客户端可供选择。2013 年 8 月,Pavel Durov 与 Nikolai Durov 兄弟创立了 Telegram 。至今,Telegram 仍在稳步发展, 其用户规模持续扩大,也在不断优化产品和功能,月均活跃超 8.6亿人。
1.1 Telegram Bot
1.1.1 简介
Telegram Bot 可以理解为完全运行在 Telegram 应用程序中的“插件”。用户通过灵活的界面与 Bot 进行交互,这些界面可以支持任何类型的任务或服务。你可以给它发送指令让它完成操作或是实现一些功能(付钱、游戏等等),或者可以在 Channel 或 Group 中发送特定消息。
1.1.2 开发相关
Telegram Bot 的技术原理基于 Telegram Bot API,这是一个基于 HTTP 的接口,允许开发者通过简单的 HTTPS 请求来控制他们的Bots。下面是一些核心要点:
-
创建 Bot:开发者首先需要通过与 Telegram 的 @BotFather(一个官方的Bot,用于创建和管理其他Bots)的交互来创建一个新的Bot。BotFather 会提供一个 token,这个 token 是访问 Telegram Bot API 并控制Bot的钥匙。
-
Bot API:Telegram Bot API 提供了一系列的方法,允许Bot接收消息、发送消息、修改消息、处理回调查询等。开发者可以通过编程方式调用这些方法来控制Bot的行为。
-
消息更新:Bot 可以通过两种方式获取消息更新:Webhooks 和轮询(polling)。
-
Webhooks:开发者可以设置一个 URL(Webhook),Telegram 会在有新的消息时推送更新到这个 URL。
-
Polling:Bot 通过周期性地向 Telegram Bot API 请求未处理的更新来获取消息。
-
-
编程语言:开发者可以使用任何能够发送 HTTPS 请求的编程语言来创建和管理 Telegram Bot。常用的语言包括 Python、JavaScript、Java、PHP 等。
-
托管:Bot 运行在开发者自己的服务器上,而不是 Telegram 的服务器。这意味着开发者需要负责维护Bot的服务器和网络基础设施。
-
集成:Bot 可以集成各种外部服务,例如数据库、支付网关、其他 API 服务等,以实现更复杂的功能。
Telegram Bot 的核心优势在于其简单性和高度的可定制性,使得开发者可以快速地开发出功能丰富的Bots 来满足各种需求。
02 TON 链
TON 是一个去中心化和开放的互联网平台,由几个组件组成。其中包括:TON 区块链、TON DNS、TON Storage 和 TONSite。TON 区块链是将 TON 的底层基础设施连接在一起以形成更大的 TON 生态系统的核心协议。
TON 专注于实现广泛的跨链互操作性,同时在高度可扩展的安全框架中运行。TON 旨在每秒处理数百万笔交易 (TPS),目标是最终达到数亿用户。
TON Blockchain 被设计为分布式超级计算机或“超级服务器”,旨在提供各种产品和服务,为新互联网的去中心化愿景的发展做出贡献。
2.1 TON 技术特点
-
多区块链架构:TON 采用了一种独特的多区块链架构,包括一个主链和多个附属链(工作链、分片链、虚拟账户链)。这种设计允许系统在保持高度安全性的同时,实现极高的可扩展性和效率。相对于比特币和以太坊主要基于单一区块链架构,有明显区别。
-
安全性和去中心化:TON 强调网络的安全性和去中心化特性,采用了先进的加密技术和分布式共识机制来保护网络免受攻击,并确保去中心化。
-
自适应分片机制:TON 的分片机制是自适应的,意味着它可以根据网络负载动态调整分片数量,从而优化处理能力和资源利用率。
-
异步通信机制:在 TON 中,节点之间的通信是异步的。这意味着节点在发送消息或执行交易时不需要等待即时的响应,从而大大提高了网络的效率和响应速度。相对于其他区块链的同步调用,TON 的异步通信机制可谓独树一帜,开发者需要重点理解此机制。
-
高吞吐量和可扩展性:TON 旨在处理大量的交易和活动,具有高吞吐量和低延迟的特点。它通过动态分片和优化的区块生成算法来实现这一目标,理论上能够支持数百万 TPS(每秒交易数)。
以下是 TON、Ethereum、Solana 的一些数据对比:
2.2 TON 钱包
用户要想使用 TON 区块链上的资产必然离不开钱包,目前 TON 的钱包有 TonKeeper、Wallet、TonSpace、Tonhub、MyTonWallet、OpenMask、Crypto Bot、Trust Wallet、SafePal 等。篇幅有限这里着重介绍 TonKeeper、Wallet、TonSpace 这三款钱包 。
2.2.1 TonKeeper
介绍:保护您的加密资产、NFT 并轻松访问 TON 应用程序。
支持平台:苹果、安卓、Chrome、Firefox等。
托管:非托管。
下载入口:官网(https://tonkeeper.com/)下载钱包
2.2.2 Wallet
介绍:Wallet 是 Telegram 的认证钱包,可以直接在 Telegram 中打开。
支持平台:Telegram
托管:托管
入口:Telegram 搜索框中输入 @Wallet
2.2.3 TON Space
介绍:集成在 Wallet 中的自托管钱包,无法在同一个账号的不同终端中共享信息。
支持平台: Telegram
托管:自托管
入口:Wallet 中选择 TON Space
03 TON和 Telegram 的关系
TON 最初是由 Telegram 的创始人 Pavel 和 Nikolai Durov 兄弟为 Telegram 设计的 Layer 1 链。2019 年,受到美国证券交易委员会 (SEC) 起诉,导致 TON 的发展受阻。2020 年,Telegram 与 SEC 达成和解,停止了 TON 的开发。后来开源社区接手了 TON 的开发, 开源社区后更名为 TON 基金会。
2023 年 9 月 Telegram 和 TON 基金会,宣布双方达成正式合作关系,整合了 TON 所推出的自托管加密钱包“TON Space” 。两者的合作是双赢关系, Telegram 为 TON 带来用户,得益于 Telegram 的 8 亿的海量用户, TON 也存在被 Mass Adoption (大规模采用) 的可能;TON 为在 Telegram 上构建 DApp 的开发者提供了 Web3 基础设施的支持。
TON 官方公布的生态系统中已经收录了 500 多个应用程序,这些应用覆盖了质押、钱包、浏览器、跨链桥、公共设施、NFT、社交、游戏、去中心化交易所、游戏等多个领域。
04 Telegram Bot 与 TON 集成
4.1 生态对象调用流程图
以下是一张简单的 Telegram Bot 与 TON 生态对象调用流程图,理清它们之间的调用关系更有助于早期技术学习。
-
TON Blockchain 指的是 TON 链。
-
TON Client 指的是应用程序与 TON 链交互的 SDK。
-
Bot 的存在可以有多种形式。
-
后端集成 Bot 是打通 Telegram 各个功能的关键。
-
与 TON 进行交互,可以是 Mini App,也可以是 Bot 后端。
4.2 Telegram Bot 创建
在 Telegram 搜索框输入 @BotFather, 点击进入,然后输入 "/newbot" 创建新 Bot, 保存 token、link等信息。
4.3 Telegram Bot 开发
下面是一个 Bot 的开发流程讲解:
-
首先 Clone 仓库(https://github.com/ton-connect/demo-telegram-bot)到本地。
-
按照 4.2 指引创建一个 telegram Bot。
-
拷贝.env.example 为 .env 文件, 修改 TELEGRAM_BOT_TOKEN、TELEGRAM_BOT_LINK 地址修改成 4.2 中获取的值, MANIFEST_URL 则是传递元信息给钱包, 包括 url、name、iconUrl、 termsOfUseUrl、privacyPolicyUrl等内容。
-
打开工程,查看 src 下的目录结
- Telegram Bot 对接
- 先查看 Bot.ts 文件
这里引入了 node-telegram-bot-api 包,导入了 token 的环境变量 。“new TelegramBot(token, { polling: true })” ,参数 token 为 Telegram Bot 的 toekn, “{ polling : ture}” 表示消息轮训的方式采用轮询的方式。
- 再看 main.ts 文件
这里是 Bot 处理命令的例子, bot.onText 为 TelegramBot 命名空间下的 onText 函数。“/\start/” 对应的命令, 后面为其对应的处理函数。使用 “ bot.sendMessage” 给当前的 msg.chat.id 会话发送信息。
4.4 Example 1: Telegram Bot 集成 Wallet
接下来根据 TON 文档(https://docs.ton.org/develop/dapps/ton-connect/tg-bot-integration),看一个Telegram Bot 集成 Wallet 的例子。下面是一个调用流程图。
TON Connect: 支持 TON 生态系统中的钱包和应用程序之间的通信的组件。
Wallets:红色图标钱包可以是 TON 钱包段落提到的。
TON BlockChain: 指的是 TON 链。
EVM BlockChain:指的是 EVM 兼容链(现在有很多 Apps Center 中的钱包就是支持以太坊生态的)。
4.4.1 代码讲解
- 先看 tonconnect/connector.ts 文件
- 再看 wallet.ts 文件
- 然后看 commands-handlers.ts 文件
handleConnectCommand 为连接钱包命令的处理函数, 使用初始化 TonnConnect, 等待选择钱包后,在进行连接钱包。
4.4.2 运行效果
输入“/connect”命令后,对应选择钱包的效果,点击 @wallet 后(也可选择 Choose Wallet 按钮),弹出。
点击 Wallet 之后,就连接上了 wallet,然后 Bot 中显示如下内容。
4.5 TON 智能合约开发语言
对于公链而言,智能合约就是生态的核心,编程语言、性能、安全等都是开发者比较关心的,那么 TON 智能合约的开发语言是怎么样呢?以下主要介绍 FunC 和 Tact。
4.5.1 FunC
FunC 是一种专门针对 TON 智能合约开发的编程语言,具备以下特性:
-
原子类型:
-
int:表示 257 位的有符号整数,自带溢出检测功能。
-
cell:代表 TVM(区块链虚拟机)单元,是 TON 区块链的基础数据存储结构。每个单元可以包含最多 1023 位数据和四个引用。
-
slice:单元片段,用于操作 cell 中的数据和引用。
-
builder:单元构建器,允许存储数据和引用,并最终构建成一个新的 cell。
-
tuple:是 TVM 中的元组类型,最多可包含 255 个不同类型的元素。
-
cont:是 TVM 的延续的类型,用于控制 TVM 程序的执行流程。
-
布尔类型的处理:
-
在 FunC 中,布尔值以整数形式表示,0 代表假,-1(257 个二进制1 )代表真。
-
空值处理:
-
用 Null 类型来表示某个原子类型值的缺失。某些函数可能会返回空值。
-
类型推断:
-
使用_和 var 表示类型空缺,这些空缺会在类型检查过程中被实际类型填充。
-
复合类型:
-
函数类型:如 A -> B,表示从 A 类型到 B 类型的函数。
-
张量类型:如(A, B, ...),表示多个有序的 A、B 等类型值的集合。
-
元组类型:如[A, B, ...],表示具有特定长度和组件类型的 TVM 元组。
-
泛型和类型变量:
-
支持泛型函数和类型变量。例如,forall X -> (X, X) duplicate(X value)是一个泛型函数。
-
用户自定义类型:
-
目前,FunC 不支持定义除上述类型构造之外的类型。
-
类型宽度
-
类型宽度指的是一个类型的所有值占用的堆栈条目数量。目前,只有已知固定宽度的类型可以定义泛型函数。
总结来说,FunC 是一个专为区块链设计的语言,其独特的类型系统和结构特别适用于处理 TON 区块链上的复杂数据和操作。
4.5.2 Tact
Tact 注重效率和简单性,且其设计易于学习和使用,非常适合智能合约。同时 Tact 是一种静态类型语言,具有简单的语法和强大的类型系统。
-
类型
-
基本类型
- Int:所有整数都是 257 位有符号整数。
- Bool:经典的布尔类型,具有真 / 假值。
- Address:标准地址。
- Slice、Cell、Builder:TVM 的低级原语。
- String:代表 TON VM 中的文本字符串。
- StringBuilder:辅助类型,允许以高效的方式连接字符串。
-
-
映射:用于将数据与相应的键关联的类型。键和值的类型有限,包括整数、布尔、单元、地址以及结构体/消息。
-
结构体和消息:结构体和消息几乎相同,唯一的区别是消息在其序列化中有一个头部,因此可以用作接收器。同时需要注意的是结构体和消息目前不支持循环类型。
-
合约:合约是 TON 区块链上智能合约的主要入口,包含初始化函数、获取器和接收器。同时合约中可以定义变量,通过 receive 函数处理外部调用,且有助于实现状态管理。
-
特性:引入了 “特质” 的概念,定义了函数、接收器和必需字段。但不规定字段存储的方式。所有特性中的字段必须在合同中显式声明。特性本身没有构造函数,所有字段的初始化也必须在主合同中完成。
4.5.3 FunC 与 Tact 的关系
由于 FunC 的学习门槛比较高,所以 TON 社区开发了类似于 TypeScript 和 Rust 的高级编程语言 Tact。
由此我们可以得出 FunC 与 Tact 之间的关系如下:
FunC — compile to --> Fift
Tact — compile to --> FunC — compile to --> Fift
这里提到的 Fift 是一种基于堆栈的通用编程语言,针对创建、调试和管理 TON 区块链智能合约进行了优化。Fift 专门设计用于与 TON 虚拟机(TVM)和 TON 区块链交互。
4.6 TON 简单合约源码分析
下面是一个参考 TON 文档(https://ton-community.github.io/tutorials/02-contract/)的简单例子,完整代码可参考:GitHub- DestinyWei/Ton-Counter: TON Counter Contract,接下来我们进行源码分析。
- 首先我们需要查看配置文件示例.env.example,复制创建名为.env的文件****
MNEMONIC 填写的是 TON 钱包的助记词,这里使用的是 Tonkeeper 钱包。
- 项目目录结构如下
counter.fc是关于 Counter 的 FunC 合约代码,主要是关于发送链上消息、读写链上数据。
wrappers 中的Counter.ts则是用于封装用于与 FunC 合约的交互接口。
scrpits 中的deployCounter.ts、getCounter.ts、sendIncrement.ts则是用于部署、读写 Counter 合约。
3.counter.fc合约源码分析
-
load_data()是一个内联函数,用于从存储单元中加载数据并返回一个整数结果。具体步骤如下:
-
调用get_data()函数获取存储单元,并将其作为切片开始解析。
-
从切片中读取一个 64 位无符号整数(uint64)。
-
将读取到的整数作为结果返回。
-
-
save_data(int counter)是一个内联函数,用于将数据写入存储单元。具体步骤如下:
-
创建一个存储单元的构建器,并将其作为初始状态。
-
将整数counter以 64 位无符号整数的形式写入构建器。
-
将构建器转换为一个存储单元,并保存在存储单元中。
-
-
recv_internal(int msg_value, cell in_msg, slice in_msg_body)是一个接收函数,用于处理接收到的内部消息。具体步骤如下:
-
检查接收到的消息体是否为空,如果为空则返回。
-
解析消息体开头编码的操作类型,使用 load_uint(32) 从切片中读取一个 32 位无符号整数。
-
调用load_data()函数从存储中加载计数器的值。
-
如果操作类型为 1(代表增量操作),则将计数器的值加 1,并调用save_data()函数将新值保存到存储中。
-
-
counter() method_id函数用于获取计数器的值。具体步骤如下:
- 调用load_data()函数从存储中加载计数器的值,并将其作为结果返回。
4.Counter.ts分析
-
createForDeploy方法用于创建一个 Counter 合约的实例,用于部署合约。
-
sendDeploy方法用于部署合约。它接受一个合约提供者provider和一个发送者via作为参数。在部署过程中,它会向合约发送 0.01 TON 的价值用于支付租金,同时不允许合约反弹(bounce)。
-
sendIncrement方法用于发送增量操作。它接受一个合约提供者provider和一个发送者via作为参数。在调用过程中,它会创建一个消息体(message body),其中包含增量操作的指令和查询 ID,并向合约发送 0.002 TON 的价值用于支付 gas 费用。
-
getCounter方法用于获取计数器值。它接受一个合约提供者provider作为参数,并从合约的状态中获取计数器的值,并返回该值。
5.deployCounter.ts分析
-
run()函数的主要功能是部署 Counter 合约和相关的钱包合约。具体步骤如下:
-
-
初始化 TonClient,并连接到测试网(testnet)的 Ton RPC 端点。
-
准备 Counter 合约的代码和数据单元(cells)用于部署。
-
创建 Counter 合约的实例。
-
检查合约是否已经部署,如果已经部署,则退出脚本。
-
打开钱包合约(WalletContractV4)。
-
检查钱包合约是否已经部署,如果未部署,则退出脚本。
-
打开钱包合约并获取当前序列号(seqno)。
-
发送部署交易并等待确认。
-
当部署交易确认后,输出相应的信息。
-
6.getCounter.ts分析
-
run()函数的主要功能是通过合约地址打开 Counter 合约实例,并调用合约上的getCounter()方法获取计数器的值。具体步骤如下:
-
初始化 TonClient,并连接到测试网(testnet)的 Ton RPC 端点。
-
解析 Counter 合约的地址,创建 Counter 合约的实例。
-
打开 Counter 合约实例。
-
调用合约的getCounter()方法获取计数器的值。
-
输出计数器的值。
-
7.sendIncrement.ts分析
-
run()函数的主要功能是执行以下操作:
-
初始化 TonClient,并连接到测试网(testnet)的 Ton RPC 端点。
-
从环境变量中获取钱包的助记词(mnemonic)。
-
将助记词转换为钱包密钥。
-
创建钱包合约实例(WalletContractV4)。
-
检查钱包合约是否已经部署,如果未部署,则退出脚本。
-
打开钱包合约并获取当前序列号(seqno)。
-
解析 Counter 合约的地址,创建 Counter 合约的实例。
-
打开 Counter 合约实例。
-
向 Counter 合约发送增量交易。
-
等待交易确认。
-
输出交易确认的信息。
-
4.7 Example 2: Telegram Bot 与 TON 合约集成
4.7.1 代码讲解
讲解完简单的合约例子源码,下一步我们讲解 DApp 非常核心的部分, Telegram Bot 与 TON 合约是如何集成的。
-
这里用 4.6 节的 Counter 合约作为集成的目标,实现在 Bot 里获取 counter 值,自增 counter 值的效果。
-
首先新增一个 counter.ts 文件,内容可以直接拷贝 4.6节中的 Counter 合约操作的封装(class Counter)。其中有 Counter类对合约的调用的封装,其中 getCounter 函数去获取当前 counter 的值, sendIncrement 是自增 counter 的值。
-
新增 Counter 值的读取函数。
在 commands-handlers.ts 文件中调用 getCounter 函数, 新增 handleGetCounterCommand 获取 Counter 值
handleGetCounterCommand 函数主要功能是执行以下操作:
a. 从 “@ton/ton” 包中引入 TonClient 类,TonClient 可以理解为连接 TON 相关接口的封装类库
b. 使用 TON RPC 地址和 TONCENTER_API_KEY (从 “@tonapibot” 的 Telegram Bot 中获取), 使用 Counter 合约地址初始化 Counter
c. 调用 “counterContract.getCounter()” 获取 Counter 合约中 counter 的值
- 新增 Counter 值的自增函数
在 commands-handlers.ts 文件中新增 handleIncrementCounterCommand 函数,执行自增 counter 值
handleIncrementCounterCommand 函数主要功能是执行以下操作:
a. 从 “@ton/ton” 包中引入 TonClient 类,TonClient 可以理解为连接 TON 相关接口的封装类库
b. 使用 TON RPC 地址和 TONCENTER_API_KEY (从 “@tonapibot” 的 Telegram Bot 中获取), 使用 Counter 合约地址初始化 Counter
c.client.open 建立 TonClient 和 链上合约的联系
d. 定义 sender 函数,用于 TonConnect 发送交易的封装
e. 调用counterContract的 sendIncrement 函数, 这里可以优化的点是对 seqno 的判断,可以参考4.6节 sendIncrement 中对 seqno 处理。
- 在 main.ts 文件, main 函数中添加获取 counter, 自增 counter 的入口。
修改完代码完成后,运行 bot 服务 。
4.7.2 运行效果
“/get_counter” 如下图
"/increment_counter" 如下图
05 总结
以上就是 Telegram & TON 生态的一些概念科普、关系梳理、example 代码讲解&效果展示。对于初学开发者来说,弄清楚官方提供的技术栈与各种功能特性如何相结合,是非常重要的,特别是与 Bot 部分,当然涉及到产品和开发相关细节是远不止这些的。
另外 TON 采用非 EVM 的标准,创造了一套完全不同于市面上任何一种(Solidity、Yul、Rust、Move、C++ 等)智能合约的技术栈,所以开发者在 Telegram & TON 生态开发 DApp,是有一定门槛的。当前除了官方文档,现存的技术参考资料相对较少,另外相对容易上手的 Tact 编程语言官方库也正处于建设阶段,离成熟还有不小距离,开发者们要有足够的心理预期。
最后希望此篇文章能给读者们带来一些帮助!
撰文|Lewis、Howe、Kahn
编辑&排版 | Cikey
设计 | WangTeng